Firewall settings
Modified VM Settings - Firewall tab to be easier to use and saner.
This commit is contained in:
parent
8e01b1488c
commit
dd990c04ac
@ -143,17 +143,6 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
def __init__(self, parent=None):
|
||||
QAbstractItemModel.__init__(self, parent)
|
||||
|
||||
self.__columnValues = {
|
||||
0: lambda x: "*" if self.children[x]["address"] == "0.0.0.0" and
|
||||
self.children[x]["netmask"] == 0 else
|
||||
self.children[x]["address"] + ("" if self.children[x][ "netmask"] == 32 else
|
||||
" /{0}".format(self.children[x][
|
||||
"netmask"])),
|
||||
1: lambda x: "any" 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"]),
|
||||
2: lambda x: self.children[x]["proto"], }
|
||||
self.__columnNames = {0: "Address", 1: "Service", 2: "Protocol", }
|
||||
self.__services = list()
|
||||
pattern = re.compile("(?P<name>[a-z][a-z0-9-]+)\s+(?P<port>[0-9]+)/(?P<protocol>[a-z]+)", re.IGNORECASE)
|
||||
@ -171,23 +160,17 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
from operator import attrgetter
|
||||
|
||||
rev = (order == Qt.AscendingOrder)
|
||||
if idx==0:
|
||||
self.children.sort(key=lambda x: x['address'], reverse = rev)
|
||||
if idx==1:
|
||||
self.children.sort(key=lambda x: self.get_service_name(x[
|
||||
"portBegin"]) if x["portEnd"] == None else x["portBegin"],
|
||||
reverse = rev)
|
||||
if idx==2:
|
||||
self.children.sort(key=lambda x: x['proto'], reverse
|
||||
= rev)
|
||||
self.children.sort(key = lambda x: self.get_column_string(idx, x)
|
||||
, reverse = rev)
|
||||
|
||||
index1 = self.createIndex(0, 0)
|
||||
index2 = self.createIndex(len(self)-1, len(self.__columnValues)-1)
|
||||
index2 = self.createIndex(len(self)-1, len(self.__columnNames)-1)
|
||||
self.dataChanged.emit(index1, index2)
|
||||
|
||||
|
||||
def get_service_name(self, port):
|
||||
for service in self.__services:
|
||||
if service[1] == port:
|
||||
if str(service[1]) == str(port):
|
||||
return service[0]
|
||||
return str(port)
|
||||
|
||||
@ -197,129 +180,122 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
return service[1]
|
||||
return None
|
||||
|
||||
def get_column_string(self, col, row):
|
||||
return self.__columnValues[col](row)
|
||||
|
||||
|
||||
def rule_to_dict(self, rule):
|
||||
def get_column_string(self, col, rule):
|
||||
# Address
|
||||
if col == 0:
|
||||
if rule.dsthost is None:
|
||||
raise FirewallModifiedOutsideError('no dsthost')
|
||||
|
||||
d = {}
|
||||
|
||||
if not rule.proto:
|
||||
d['proto'] = 'any'
|
||||
d['portBegin'] = 'any'
|
||||
d['portEnd'] = None
|
||||
|
||||
return "*"
|
||||
else:
|
||||
d['proto'] = rule.proto
|
||||
if rule.dsthost.type == 'dst4'\
|
||||
and rule.dsthost.prefixlen == '32':
|
||||
return str(rule.dsthost)[:-3]
|
||||
elif rule.dsthost.type == 'dst6'\
|
||||
and rule.dsthost.prefixlen == '128':
|
||||
return str(rule.dsthost)[:-4]
|
||||
else:
|
||||
return str(rule.dsthost)
|
||||
|
||||
# Service
|
||||
if col == 1:
|
||||
if rule.dstports is None:
|
||||
raise FirewallModifiedOutsideError('no dstport')
|
||||
d['portBegin'] = rule.dstports.range[0]
|
||||
d['portEnd'] = rule.dstports.range[1] \
|
||||
if rule.dstports.range[0] != rule.dstports.range[1] \
|
||||
else None
|
||||
|
||||
if rule.dsthost.type == 'dsthost':
|
||||
d['address'] = str(rule.dsthost)
|
||||
d['netmask'] = 32
|
||||
elif rule.dsthost.type == 'dst4':
|
||||
network = ipaddress.IPv4Network(rule.dsthost)
|
||||
d['address'] = str(network.network_address)
|
||||
d['netmask'] = int(network.prefixlen)
|
||||
return "any"
|
||||
elif rule.dstports.range[0] != rule.dstports.range[1]:
|
||||
return str(rule.dstports)
|
||||
else:
|
||||
raise FirewallModifiedOutsideError(
|
||||
'cannot map dsthost.type={!s}'.format(rule.dsthost))
|
||||
return self.get_service_name(rule.dstports)
|
||||
|
||||
if rule.expire is not None:
|
||||
d['expire'] = int(rule.expire)
|
||||
|
||||
return d
|
||||
# Protocol
|
||||
if col == 2:
|
||||
if rule.proto is None:
|
||||
return "any"
|
||||
else:
|
||||
return str(rule.proto)
|
||||
return "unknown"
|
||||
|
||||
def get_firewall_conf(self, vm):
|
||||
conf = {
|
||||
'allow': None,
|
||||
'allowDns': False,
|
||||
'allowIcmp': False,
|
||||
'allowYumProxy': False,
|
||||
'expire': 0,
|
||||
'rules': [],
|
||||
}
|
||||
|
||||
allowDns = False
|
||||
allowIcmp = False
|
||||
common_action = None
|
||||
tentative_action = None
|
||||
|
||||
reversed_rules = list(reversed(vm.firewall.rules))
|
||||
last_rule = reversed_rules.pop(0)
|
||||
|
||||
if last_rule == qubesadmin.firewall.Rule('action=accept') \
|
||||
or last_rule == qubesadmin.firewall.Rule('action=drop'):
|
||||
common_action = last_rule.action
|
||||
else:
|
||||
FirewallModifiedOutsideError('Last rule must be either '
|
||||
'drop all or accept all.')
|
||||
|
||||
dns_rule = qubesadmin.firewall.Rule(None,
|
||||
action='accept', specialtarget='dns')
|
||||
icmp_rule = qubesadmin.firewall.Rule(None,
|
||||
action='accept', proto='icmp')
|
||||
while reversed_rules:
|
||||
rule = reversed_rules[0]
|
||||
if rule.dsthost is not None or rule.proto is not None:
|
||||
break
|
||||
tentative_action = reversed_rules.pop(0).action
|
||||
rule = reversed_rules.pop(0)
|
||||
|
||||
if not reversed_rules:
|
||||
conf['allow'] = tentative_action == 'accept'
|
||||
return conf
|
||||
|
||||
for rule in reversed_rules:
|
||||
if rule.specialtarget == 'dns':
|
||||
conf['allowDns'] = (rule.action == 'accept')
|
||||
if rule == dns_rule:
|
||||
allowDns = True
|
||||
continue
|
||||
|
||||
if rule.proto == 'icmp':
|
||||
if rule.icmptype is not None:
|
||||
raise FirewallModifiedOutsideError(
|
||||
'cannot map icmptype != None')
|
||||
conf['allowIcmp'] = (rule.action == 'accept')
|
||||
if rule.proto == icmp_rule:
|
||||
allowIcmp = True
|
||||
continue
|
||||
|
||||
if common_action is None:
|
||||
common_action = rule.action
|
||||
elif common_action != rule.action:
|
||||
raise FirewallModifiedOutsideError('incoherent action')
|
||||
if rule.specialtarget is not None or rule.icmptype is not None:
|
||||
raise FirewallModifiedOutsideError("Rule type unknown!")
|
||||
|
||||
conf['rules'].insert(0, self.rule_to_dict(rule))
|
||||
if (rule.dsthost is not None or rule.proto is not None) \
|
||||
and rule.expire is None:
|
||||
if rule.action == 'accept':
|
||||
conf['rules'].insert(0, rule)
|
||||
continue
|
||||
else:
|
||||
raise FirewallModifiedOutsideError('No blacklist support.')
|
||||
|
||||
if rule.expire is not None and rule.dsthost is None \
|
||||
and rule.proto is None:
|
||||
conf['expire'] = int(str(rule.expire))
|
||||
continue
|
||||
|
||||
raise FirewallModifiedOutsideError('it does not add up.')
|
||||
|
||||
conf['allow'] = (common_action == 'accept')
|
||||
|
||||
if not allowIcmp and not conf['allow']:
|
||||
raise FirewallModifiedOutsideError('ICMP must be allowed.')
|
||||
|
||||
if not allowDns and not conf['allow']:
|
||||
raise FirewallModifiedOutsideError('DNS must be allowed')
|
||||
|
||||
if common_action is None or common_action != tentative_action:
|
||||
# we've got only specialtarget and/or icmp
|
||||
conf['allow'] = tentative_action == 'accept'
|
||||
return conf
|
||||
|
||||
raise FirewallModifiedOutsideError('it does not add up')
|
||||
|
||||
def write_firewall_conf(self, vm, conf):
|
||||
common_action = qubesadmin.firewall.Action(
|
||||
'drop' if conf['allow'] else 'accept')
|
||||
|
||||
rules = []
|
||||
|
||||
for rule in conf['rules']:
|
||||
kwargs = {}
|
||||
if rule['proto'] != 'any':
|
||||
kwargs['proto'] = rule['proto']
|
||||
if rule['portBegin'] != 'any':
|
||||
kwargs['dstports'] = '-'.join(map(str, filter((lambda x: x),
|
||||
(rule['portBegin'], rule['portEnd']))))
|
||||
rules.append(rule)
|
||||
|
||||
netmask = str(rule['netmask']) if rule['netmask'] != 32 else None
|
||||
|
||||
rules.append(qubesadmin.firewall.Rule(None,
|
||||
action=common_action,
|
||||
dsthost='/'.join(map(str, filter((lambda x: x),
|
||||
(rule['address'], netmask)))),
|
||||
**kwargs))
|
||||
|
||||
if conf['allowDns']:
|
||||
if not conf['allow']:
|
||||
rules.append(qubesadmin.firewall.Rule(None,
|
||||
action='accept', specialtarget='dns'))
|
||||
|
||||
if conf['allowIcmp']:
|
||||
if not conf['allow']:
|
||||
rules.append(qubesadmin.firewall.Rule(None,
|
||||
action='accept', proto='icmp'))
|
||||
|
||||
if common_action == 'drop':
|
||||
if conf['allow']:
|
||||
rules.append(qubesadmin.firewall.Rule(None,
|
||||
action='accept'))
|
||||
else:
|
||||
rules.append(qubesadmin.firewall.Rule(None,
|
||||
action = 'drop'))
|
||||
|
||||
vm.firewall.rules = rules
|
||||
|
||||
@ -331,58 +307,98 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
conf = self.get_firewall_conf(vm)
|
||||
|
||||
self.allow = conf["allow"]
|
||||
self.allowDns = conf["allowDns"]
|
||||
self.allowIcmp = conf["allowIcmp"]
|
||||
self.allowYumProxy = conf["allowYumProxy"]
|
||||
self.tempFullAccessExpireTime = 0
|
||||
|
||||
self.tempFullAccessExpireTime = conf['expire']
|
||||
|
||||
for rule in conf["rules"]:
|
||||
self.appendChild(rule)
|
||||
if "expire" in rule and rule["address"] == "0.0.0.0":
|
||||
self.tempFullAccessExpireTime = rule["expire"]
|
||||
|
||||
def get_vm_name(self):
|
||||
return self.__vm.name
|
||||
|
||||
def apply_rules(self, allow, dns, icmp, yumproxy, tempFullAccess=False,
|
||||
def apply_rules(self, allow, tempFullAccess=False,
|
||||
tempFullAccessTime=None):
|
||||
assert self.__vm is not None
|
||||
|
||||
if self.allow != allow or self.allowDns != dns or \
|
||||
self.allowIcmp != icmp or self.allowYumProxy != yumproxy or \
|
||||
if self.allow != allow or \
|
||||
(self.tempFullAccessExpireTime != 0) != tempFullAccess:
|
||||
self.fw_changed = True
|
||||
|
||||
conf = { "allow": allow,
|
||||
"allowDns": dns,
|
||||
"allowIcmp": icmp,
|
||||
"allowYumProxy": yumproxy,
|
||||
"rules": list()
|
||||
}
|
||||
|
||||
for rule in self.children:
|
||||
if "expire" in rule and rule["address"] == "0.0.0.0" and \
|
||||
rule["netmask"] == 0 and rule["proto"] == "any":
|
||||
# rule already present, update its time
|
||||
if tempFullAccess:
|
||||
rule["expire"] = \
|
||||
int(datetime.datetime.now().strftime("%s")) + \
|
||||
tempFullAccessTime*60
|
||||
tempFullAccess = False
|
||||
conf["rules"].append(rule)
|
||||
conf['rules'].extend(self.children)
|
||||
|
||||
if tempFullAccess and not allow:
|
||||
conf["rules"].append({"address": "0.0.0.0",
|
||||
"netmask": 0,
|
||||
"proto": "any",
|
||||
"expire": int(
|
||||
datetime.datetime.now().strftime("%s"))+\
|
||||
tempFullAccessTime*60
|
||||
})
|
||||
conf["rules"].append(qubesadmin.firewall.Rule(None,action='accept'
|
||||
, expire=int(datetime.datetime.now().strftime("%s"))+\
|
||||
tempFullAccessTime*60))
|
||||
|
||||
if self.fw_changed:
|
||||
self.write_firewall_conf(self.__vm, conf)
|
||||
|
||||
def populate_edit_dialog(self, dialog, row):
|
||||
address = self.get_column_string(0, self.children[row])
|
||||
dialog.addressComboBox.setItemText(0, address)
|
||||
dialog.addressComboBox.setCurrentIndex(0)
|
||||
service = self.get_column_string(1, self.children[row])
|
||||
if service == "any":
|
||||
service = ""
|
||||
dialog.serviceComboBox.setItemText(0, service)
|
||||
dialog.serviceComboBox.setCurrentIndex(0)
|
||||
protocol = self.get_column_string(2, self.children[row])
|
||||
if protocol == "tcp":
|
||||
dialog.tcp_radio.setChecked(True)
|
||||
elif protocol == "udp":
|
||||
dialog.udp_radio.setChecked(True)
|
||||
else:
|
||||
dialog.any_radio.setChecked(True)
|
||||
|
||||
def run_rule_dialog(self, dialog, row = None):
|
||||
if dialog.exec_():
|
||||
|
||||
address = str(dialog.addressComboBox.currentText())
|
||||
service = str(dialog.serviceComboBox.currentText())
|
||||
|
||||
rule = qubesadmin.firewall.Rule(None,action='accept')
|
||||
|
||||
if address is not None and address != "*":
|
||||
try:
|
||||
rule.dsthost = address
|
||||
except ValueError:
|
||||
QMessageBox.warning(None, self.tr("Invalid address"),
|
||||
self.tr("Address '{0}' is invalid.").format(address))
|
||||
|
||||
if dialog.tcp_radio.isChecked():
|
||||
rule.proto = 'tcp'
|
||||
elif dialog.udp_radio.isChecked():
|
||||
rule.proto = 'udp'
|
||||
|
||||
if '-' in service:
|
||||
try:
|
||||
rule.dstports = service
|
||||
except ValueError:
|
||||
QMessageBox.warning(None, self.tr("Invalid port or service"),
|
||||
self.tr("Port number or service '{0}' is invalid.")
|
||||
.format(service))
|
||||
elif service is not None:
|
||||
try:
|
||||
rule.dstports = service
|
||||
except (TypeError, ValueError) as ex:
|
||||
if self.get_service_port(service) is not None:
|
||||
rule.dstports = self.get_service_port(service)
|
||||
else:
|
||||
QMessageBox.warning(None,
|
||||
self.tr("Invalid port or service"),
|
||||
self.tr("Port number or service '{0}' is invalid.")
|
||||
.format(service))
|
||||
|
||||
if row is not None:
|
||||
self.setChild(row, rule)
|
||||
else:
|
||||
self.appendChild(rule)
|
||||
|
||||
def index(self, row, column, parent=QModelIndex()):
|
||||
if not self.hasIndex(row, column, parent):
|
||||
return QModelIndex()
|
||||
@ -396,7 +412,7 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
return len(self)
|
||||
|
||||
def columnCount(self, parent=QModelIndex()):
|
||||
return len(self.__columnValues)
|
||||
return len(self.__columnNames)
|
||||
|
||||
def hasChildren(self, index=QModelIndex()):
|
||||
parentItem = index.internalPointer()
|
||||
@ -407,7 +423,8 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
if index.isValid() and role == Qt.DisplayRole:
|
||||
return self.__columnValues[index.column()](index.row())
|
||||
return self.get_column_string(index.column()
|
||||
,self.children[index.row()])
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if section < len(self.__columnNames) \
|
||||
|
@ -80,7 +80,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
||||
|
||||
self.tabWidget.currentChanged.connect(self.current_tab_changed)
|
||||
|
||||
# self.tabWidget.setTabEnabled(self.tabs_indices["firewall"], vm.is_networked() and not vm.provides_network)
|
||||
self.tabWidget.setTabEnabled(self.tabs_indices["firewall"],
|
||||
vm.netvm is not None and not vm.provides_network)
|
||||
|
||||
###### basic tab
|
||||
self.__init_basic_tab__()
|
||||
@ -96,8 +97,12 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
||||
###### firewall tab
|
||||
if self.tabWidget.isTabEnabled(self.tabs_indices['firewall']):
|
||||
model = QubesFirewallRulesModel()
|
||||
try:
|
||||
model.set_vm(vm)
|
||||
self.set_fw_model(model)
|
||||
self.firewallModifiedOutsidelabel.setVisible(False)
|
||||
except FirewallModifiedOutsideError as ex:
|
||||
self.disable_all_fw_conf()
|
||||
|
||||
self.newRuleButton.clicked.connect(self.new_rule_button_pressed)
|
||||
self.editRuleButton.clicked.connect(self.edit_rule_button_pressed)
|
||||
@ -175,11 +180,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
||||
ret.append(self.tr('Error while saving changes: ') + str(ex))
|
||||
|
||||
try:
|
||||
if self.tabWidget.isTabEnabled(self.tabs_indices["firewall"]):
|
||||
if self.policyAllowRadioButton.isEnabled():
|
||||
self.fw_model.apply_rules(self.policyAllowRadioButton.isChecked(),
|
||||
self.dnsCheckBox.isChecked(),
|
||||
self.icmpCheckBox.isChecked(),
|
||||
self.yumproxyCheckBox.isChecked(),
|
||||
self.tempFullAccess.isChecked(),
|
||||
self.tempFullAccessTime.value())
|
||||
if self.fw_model.fw_changed:
|
||||
@ -773,114 +775,58 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
||||
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
|
||||
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
|
||||
self.set_allow(model.allow)
|
||||
self.dnsCheckBox.setChecked(model.allowDns)
|
||||
self.icmpCheckBox.setChecked(model.allowIcmp)
|
||||
self.yumproxyCheckBox.setChecked(model.allowYumProxy)
|
||||
if model.tempFullAccessExpireTime:
|
||||
self.tempFullAccess.setChecked(True)
|
||||
self.tempFullAccessTime.setValue(
|
||||
(model.tempFullAccessExpireTime -
|
||||
int(datetime.datetime.now().strftime("%s")))/60)
|
||||
|
||||
def disable_all_fw_conf(self):
|
||||
self.firewallModifiedOutsidelabel.setVisible(True)
|
||||
self.policyAllowRadioButton.setEnabled(False)
|
||||
self.policyDenyRadioButton.setEnabled(False)
|
||||
self.rulesTreeView.setEnabled(False)
|
||||
self.newRuleButton.setEnabled(False)
|
||||
self.editRuleButton.setEnabled(False)
|
||||
self.deleteRuleButton.setEnabled(False)
|
||||
self.firewalRulesLabel.setEnabled(False)
|
||||
self.tempFullAccessWidget.setEnabled(False)
|
||||
|
||||
def set_allow(self, allow):
|
||||
self.policyAllowRadioButton.setChecked(allow)
|
||||
self.policyDenyRadioButton.setChecked(not allow)
|
||||
self.policy_changed(allow)
|
||||
|
||||
def policy_changed(self, checked):
|
||||
self.tempFullAccessWidget.setEnabled(self.policyDenyRadioButton.isChecked())
|
||||
self.rulesTreeView.setEnabled(self.policyDenyRadioButton.isChecked())
|
||||
self.newRuleButton.setEnabled(self.policyDenyRadioButton.isChecked())
|
||||
self.editRuleButton.setEnabled(self.policyDenyRadioButton.isChecked())
|
||||
self.deleteRuleButton.setEnabled(self.policyDenyRadioButton.isChecked())
|
||||
self.firewalRulesLabel.setEnabled(
|
||||
self.policyDenyRadioButton.isChecked())
|
||||
self.tempFullAccessWidget.setEnabled(
|
||||
self.policyDenyRadioButton.isChecked())
|
||||
|
||||
def new_rule_button_pressed(self):
|
||||
dialog = NewFwRuleDlg()
|
||||
self.run_rule_dialog(dialog)
|
||||
self.fw_model.run_rule_dialog(dialog)
|
||||
|
||||
def edit_rule_button_pressed(self):
|
||||
|
||||
selected = self.rulesTreeView.selectedIndexes()
|
||||
|
||||
if len(selected) > 0:
|
||||
dialog = NewFwRuleDlg()
|
||||
dialog.set_ok_enabled(True)
|
||||
selected = self.rulesTreeView.selectedIndexes()
|
||||
if len(selected) > 0:
|
||||
row = self.rulesTreeView.selectedIndexes().pop().row()
|
||||
address = self.fw_model.get_column_string(0, row).replace(' ', '')
|
||||
dialog.addressComboBox.setItemText(0, address)
|
||||
dialog.addressComboBox.setCurrentIndex(0)
|
||||
service = self.fw_model.get_column_string(1, row)
|
||||
if service == "any":
|
||||
service = ""
|
||||
dialog.serviceComboBox.setItemText(0, service)
|
||||
dialog.serviceComboBox.setCurrentIndex(0)
|
||||
protocol = self.fw_model.get_column_string(2, row)
|
||||
if protocol == "tcp":
|
||||
dialog.tcp_radio.setChecked(True)
|
||||
elif protocol == "udp":
|
||||
dialog.udp_radio.setChecked(True)
|
||||
else:
|
||||
dialog.any_radio.setChecked(True)
|
||||
|
||||
self.run_rule_dialog(dialog, row)
|
||||
self.fw_model.populate_edit_dialog(dialog, row)
|
||||
self.fw_model.run_rule_dialog(dialog, row)
|
||||
|
||||
def delete_rule_button_pressed(self):
|
||||
for i in set([index.row() for index in self.rulesTreeView.selectedIndexes()]):
|
||||
for i in set([index.row() for index
|
||||
in self.rulesTreeView.selectedIndexes()]):
|
||||
self.fw_model.removeChild(i)
|
||||
|
||||
def run_rule_dialog(self, dialog, row = None):
|
||||
if dialog.exec_():
|
||||
address = str(dialog.addressComboBox.currentText())
|
||||
service = str(dialog.serviceComboBox.currentText())
|
||||
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 dialog.any_radio.isChecked():
|
||||
protocol = "any"
|
||||
port = 0
|
||||
else:
|
||||
if dialog.tcp_radio.isChecked():
|
||||
protocol = "tcp"
|
||||
elif dialog.udp_radio.isChecked():
|
||||
protocol = "udp"
|
||||
else:
|
||||
protocol = "any"
|
||||
|
||||
try:
|
||||
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:
|
||||
port = self.fw_model.get_service_port(service)
|
||||
|
||||
if port is not None:
|
||||
if port2 is not None and port2 <= port:
|
||||
QMessageBox.warning(None, self.tr("Invalid service ports range"),
|
||||
self.tr("Port {0} is lower than port {1}.").format(
|
||||
port2, port))
|
||||
else:
|
||||
item = {"address": address,
|
||||
"netmask": netmask,
|
||||
"portBegin": port,
|
||||
"portEnd": port2,
|
||||
"proto": protocol,
|
||||
}
|
||||
if row is not None:
|
||||
self.fw_model.setChild(row, item)
|
||||
else:
|
||||
self.fw_model.appendChild(item)
|
||||
else:
|
||||
QMessageBox.warning(None, self.tr("Invalid service name"),
|
||||
self.tr("Service '{0}' is unknown.").format(service))
|
||||
|
||||
|
||||
# Bases on the original code by:
|
||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||
|
@ -31,10 +31,22 @@
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<item row="2" column="2">
|
||||
<widget class="QRadioButton" name="udp_radio">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
<string>UDP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -45,13 +57,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="serviceComboBox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
@ -59,6 +64,31 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QRadioButton" name="any_radio">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>71</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Any </string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="addressComboBox">
|
||||
<property name="editable">
|
||||
@ -66,6 +96,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="serviceComboBox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QRadioButton" name="tcp_radio">
|
||||
<property name="sizePolicy">
|
||||
@ -85,44 +122,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QRadioButton" name="udp_radio">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>UDP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QRadioButton" name="any_radio">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>71</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Any </string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -29,7 +29,7 @@
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="basic_tab">
|
||||
<property name="locale">
|
||||
@ -655,48 +655,101 @@
|
||||
<string>Firewall rules</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="policyAllowRadioButton">
|
||||
<property name="text">
|
||||
<string>Allow network access except...</string>
|
||||
<string>Allow all outgoing Internet connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="icmpCheckBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>323</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="policyDenyRadioButton">
|
||||
<property name="text">
|
||||
<string>Allow ICMP traffic</string>
|
||||
<string>Limit outgoing Internet connections to ...</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>NOTE: To block all network access, set Networking to (none) on the Basic settings tab. This tab provides a very simplified firewall configuration. All DNS requests and ICMP (pings) will be allowed. For more granular control, use the command line tool qvm-firewall.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="policyDenyRadioButton">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="firewalRulesLabel">
|
||||
<property name="text">
|
||||
<string>Deny network access except...</string>
|
||||
<string>List of allowed (whitelisted) addresses:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QWidget" name="tempFullAccessWidget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="tempFullAccess">
|
||||
<property name="text">
|
||||
<string>Allow full access for </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="dnsCheckBox">
|
||||
<property name="text">
|
||||
<string>Allow DNS queries</string>
|
||||
<widget class="QSpinBox" name="tempFullAccessTime">
|
||||
<property name="suffix">
|
||||
<string> min</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="firewallRulesLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
@ -805,48 +858,57 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="yumproxyCheckBox">
|
||||
<property name="text">
|
||||
<string>Allow connections to Updates Proxy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QWidget" name="tempFullAccessWidget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="tempFullAccess">
|
||||
<widget class="QLabel" name="firewallModifiedOutsidelabel">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>139</red>
|
||||
<green>142</green>
|
||||
<blue>142</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow full access for </string>
|
||||
<string>Firewall has been modified manually - please use qvm-firewall for any further configuration.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="tempFullAccessTime">
|
||||
<property name="suffix">
|
||||
<string> min</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="devices_tab">
|
||||
@ -1035,11 +1097,6 @@
|
||||
<tabstop>vcpus</tabstop>
|
||||
<tabstop>include_in_balancing</tabstop>
|
||||
<tabstop>kernel</tabstop>
|
||||
<tabstop>policyAllowRadioButton</tabstop>
|
||||
<tabstop>policyDenyRadioButton</tabstop>
|
||||
<tabstop>icmpCheckBox</tabstop>
|
||||
<tabstop>dnsCheckBox</tabstop>
|
||||
<tabstop>yumproxyCheckBox</tabstop>
|
||||
<tabstop>newRuleButton</tabstop>
|
||||
<tabstop>rulesTreeView</tabstop>
|
||||
<tabstop>editRuleButton</tabstop>
|
||||
|
Loading…
Reference in New Issue
Block a user