Merge remote-tracking branch 'qubesos/pr/45'
* qubesos/pr/45: Firewall settings
This commit is contained in:
commit
d165bd33b6
@ -143,17 +143,6 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QAbstractItemModel.__init__(self, parent)
|
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.__columnNames = {0: "Address", 1: "Service", 2: "Protocol", }
|
||||||
self.__services = list()
|
self.__services = list()
|
||||||
pattern = re.compile("(?P<name>[a-z][a-z0-9-]+)\s+(?P<port>[0-9]+)/(?P<protocol>[a-z]+)", re.IGNORECASE)
|
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
|
from operator import attrgetter
|
||||||
|
|
||||||
rev = (order == Qt.AscendingOrder)
|
rev = (order == Qt.AscendingOrder)
|
||||||
if idx==0:
|
self.children.sort(key = lambda x: self.get_column_string(idx, x)
|
||||||
self.children.sort(key=lambda x: x['address'], reverse = rev)
|
, 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)
|
|
||||||
index1 = self.createIndex(0, 0)
|
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)
|
self.dataChanged.emit(index1, index2)
|
||||||
|
|
||||||
|
|
||||||
def get_service_name(self, port):
|
def get_service_name(self, port):
|
||||||
for service in self.__services:
|
for service in self.__services:
|
||||||
if service[1] == port:
|
if str(service[1]) == str(port):
|
||||||
return service[0]
|
return service[0]
|
||||||
return str(port)
|
return str(port)
|
||||||
|
|
||||||
@ -197,129 +180,122 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
return service[1]
|
return service[1]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_column_string(self, col, row):
|
def get_column_string(self, col, rule):
|
||||||
return self.__columnValues[col](row)
|
# Address
|
||||||
|
if col == 0:
|
||||||
|
|
||||||
def rule_to_dict(self, rule):
|
|
||||||
if rule.dsthost is None:
|
if rule.dsthost is None:
|
||||||
raise FirewallModifiedOutsideError('no dsthost')
|
return "*"
|
||||||
|
|
||||||
d = {}
|
|
||||||
|
|
||||||
if not rule.proto:
|
|
||||||
d['proto'] = 'any'
|
|
||||||
d['portBegin'] = 'any'
|
|
||||||
d['portEnd'] = None
|
|
||||||
|
|
||||||
else:
|
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:
|
if rule.dstports is None:
|
||||||
raise FirewallModifiedOutsideError('no dstport')
|
return "any"
|
||||||
d['portBegin'] = rule.dstports.range[0]
|
elif rule.dstports.range[0] != rule.dstports.range[1]:
|
||||||
d['portEnd'] = rule.dstports.range[1] \
|
return str(rule.dstports)
|
||||||
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)
|
|
||||||
else:
|
else:
|
||||||
raise FirewallModifiedOutsideError(
|
return self.get_service_name(rule.dstports)
|
||||||
'cannot map dsthost.type={!s}'.format(rule.dsthost))
|
|
||||||
|
|
||||||
if rule.expire is not None:
|
# Protocol
|
||||||
d['expire'] = int(rule.expire)
|
if col == 2:
|
||||||
|
if rule.proto is None:
|
||||||
return d
|
return "any"
|
||||||
|
else:
|
||||||
|
return str(rule.proto)
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
def get_firewall_conf(self, vm):
|
def get_firewall_conf(self, vm):
|
||||||
conf = {
|
conf = {
|
||||||
'allow': None,
|
'allow': None,
|
||||||
'allowDns': False,
|
'expire': 0,
|
||||||
'allowIcmp': False,
|
|
||||||
'allowYumProxy': False,
|
|
||||||
'rules': [],
|
'rules': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allowDns = False
|
||||||
|
allowIcmp = False
|
||||||
common_action = None
|
common_action = None
|
||||||
tentative_action = None
|
|
||||||
|
|
||||||
reversed_rules = list(reversed(vm.firewall.rules))
|
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:
|
while reversed_rules:
|
||||||
rule = reversed_rules[0]
|
rule = reversed_rules.pop(0)
|
||||||
if rule.dsthost is not None or rule.proto is not None:
|
|
||||||
break
|
|
||||||
tentative_action = reversed_rules.pop(0).action
|
|
||||||
|
|
||||||
if not reversed_rules:
|
if rule == dns_rule:
|
||||||
conf['allow'] = tentative_action == 'accept'
|
allowDns = True
|
||||||
return conf
|
|
||||||
|
|
||||||
for rule in reversed_rules:
|
|
||||||
if rule.specialtarget == 'dns':
|
|
||||||
conf['allowDns'] = (rule.action == 'accept')
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if rule.proto == 'icmp':
|
if rule.proto == icmp_rule:
|
||||||
if rule.icmptype is not None:
|
allowIcmp = True
|
||||||
raise FirewallModifiedOutsideError(
|
|
||||||
'cannot map icmptype != None')
|
|
||||||
conf['allowIcmp'] = (rule.action == 'accept')
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if common_action is None:
|
if rule.specialtarget is not None or rule.icmptype is not None:
|
||||||
common_action = rule.action
|
raise FirewallModifiedOutsideError("Rule type unknown!")
|
||||||
elif common_action != rule.action:
|
|
||||||
raise FirewallModifiedOutsideError('incoherent action')
|
|
||||||
|
|
||||||
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
|
return conf
|
||||||
|
|
||||||
raise FirewallModifiedOutsideError('it does not add up')
|
|
||||||
|
|
||||||
def write_firewall_conf(self, vm, conf):
|
def write_firewall_conf(self, vm, conf):
|
||||||
common_action = qubesadmin.firewall.Action(
|
|
||||||
'drop' if conf['allow'] else 'accept')
|
|
||||||
|
|
||||||
rules = []
|
rules = []
|
||||||
|
|
||||||
for rule in conf['rules']:
|
for rule in conf['rules']:
|
||||||
kwargs = {}
|
rules.append(rule)
|
||||||
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']))))
|
|
||||||
|
|
||||||
netmask = str(rule['netmask']) if rule['netmask'] != 32 else None
|
if not conf['allow']:
|
||||||
|
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
|
||||||
action=common_action,
|
|
||||||
dsthost='/'.join(map(str, filter((lambda x: x),
|
|
||||||
(rule['address'], netmask)))),
|
|
||||||
**kwargs))
|
|
||||||
|
|
||||||
if conf['allowDns']:
|
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(None,
|
||||||
action='accept', specialtarget='dns'))
|
action='accept', specialtarget='dns'))
|
||||||
|
|
||||||
if conf['allowIcmp']:
|
if not conf['allow']:
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(None,
|
||||||
action='accept', proto='icmp'))
|
action='accept', proto='icmp'))
|
||||||
|
|
||||||
if common_action == 'drop':
|
if conf['allow']:
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(None,
|
||||||
action='accept'))
|
action='accept'))
|
||||||
|
else:
|
||||||
|
rules.append(qubesadmin.firewall.Rule(None,
|
||||||
|
action = 'drop'))
|
||||||
|
|
||||||
vm.firewall.rules = rules
|
vm.firewall.rules = rules
|
||||||
|
|
||||||
@ -331,58 +307,98 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
conf = self.get_firewall_conf(vm)
|
conf = self.get_firewall_conf(vm)
|
||||||
|
|
||||||
self.allow = conf["allow"]
|
self.allow = conf["allow"]
|
||||||
self.allowDns = conf["allowDns"]
|
|
||||||
self.allowIcmp = conf["allowIcmp"]
|
self.tempFullAccessExpireTime = conf['expire']
|
||||||
self.allowYumProxy = conf["allowYumProxy"]
|
|
||||||
self.tempFullAccessExpireTime = 0
|
|
||||||
|
|
||||||
for rule in conf["rules"]:
|
for rule in conf["rules"]:
|
||||||
self.appendChild(rule)
|
self.appendChild(rule)
|
||||||
if "expire" in rule and rule["address"] == "0.0.0.0":
|
|
||||||
self.tempFullAccessExpireTime = rule["expire"]
|
|
||||||
|
|
||||||
def get_vm_name(self):
|
def get_vm_name(self):
|
||||||
return self.__vm.name
|
return self.__vm.name
|
||||||
|
|
||||||
def apply_rules(self, allow, dns, icmp, yumproxy, tempFullAccess=False,
|
def apply_rules(self, allow, tempFullAccess=False,
|
||||||
tempFullAccessTime=None):
|
tempFullAccessTime=None):
|
||||||
assert self.__vm is not None
|
assert self.__vm is not None
|
||||||
|
|
||||||
if self.allow != allow or self.allowDns != dns or \
|
if self.allow != allow or \
|
||||||
self.allowIcmp != icmp or self.allowYumProxy != yumproxy or \
|
|
||||||
(self.tempFullAccessExpireTime != 0) != tempFullAccess:
|
(self.tempFullAccessExpireTime != 0) != tempFullAccess:
|
||||||
self.fw_changed = True
|
self.fw_changed = True
|
||||||
|
|
||||||
conf = { "allow": allow,
|
conf = { "allow": allow,
|
||||||
"allowDns": dns,
|
|
||||||
"allowIcmp": icmp,
|
|
||||||
"allowYumProxy": yumproxy,
|
|
||||||
"rules": list()
|
"rules": list()
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule in self.children:
|
conf['rules'].extend(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)
|
|
||||||
|
|
||||||
if tempFullAccess and not allow:
|
if tempFullAccess and not allow:
|
||||||
conf["rules"].append({"address": "0.0.0.0",
|
conf["rules"].append(qubesadmin.firewall.Rule(None,action='accept'
|
||||||
"netmask": 0,
|
, expire=int(datetime.datetime.now().strftime("%s"))+\
|
||||||
"proto": "any",
|
tempFullAccessTime*60))
|
||||||
"expire": int(
|
|
||||||
datetime.datetime.now().strftime("%s"))+\
|
|
||||||
tempFullAccessTime*60
|
|
||||||
})
|
|
||||||
|
|
||||||
if self.fw_changed:
|
if self.fw_changed:
|
||||||
self.write_firewall_conf(self.__vm, conf)
|
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()):
|
def index(self, row, column, parent=QModelIndex()):
|
||||||
if not self.hasIndex(row, column, parent):
|
if not self.hasIndex(row, column, parent):
|
||||||
return QModelIndex()
|
return QModelIndex()
|
||||||
@ -396,7 +412,7 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
return len(self)
|
return len(self)
|
||||||
|
|
||||||
def columnCount(self, parent=QModelIndex()):
|
def columnCount(self, parent=QModelIndex()):
|
||||||
return len(self.__columnValues)
|
return len(self.__columnNames)
|
||||||
|
|
||||||
def hasChildren(self, index=QModelIndex()):
|
def hasChildren(self, index=QModelIndex()):
|
||||||
parentItem = index.internalPointer()
|
parentItem = index.internalPointer()
|
||||||
@ -407,7 +423,8 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
|||||||
|
|
||||||
def data(self, index, role=Qt.DisplayRole):
|
def data(self, index, role=Qt.DisplayRole):
|
||||||
if index.isValid() and 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):
|
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||||
if section < len(self.__columnNames) \
|
if section < len(self.__columnNames) \
|
||||||
|
@ -80,7 +80,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
|
|
||||||
self.tabWidget.currentChanged.connect(self.current_tab_changed)
|
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
|
###### basic tab
|
||||||
self.__init_basic_tab__()
|
self.__init_basic_tab__()
|
||||||
@ -96,8 +97,12 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
###### firewall tab
|
###### firewall tab
|
||||||
if self.tabWidget.isTabEnabled(self.tabs_indices['firewall']):
|
if self.tabWidget.isTabEnabled(self.tabs_indices['firewall']):
|
||||||
model = QubesFirewallRulesModel()
|
model = QubesFirewallRulesModel()
|
||||||
|
try:
|
||||||
model.set_vm(vm)
|
model.set_vm(vm)
|
||||||
self.set_fw_model(model)
|
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.newRuleButton.clicked.connect(self.new_rule_button_pressed)
|
||||||
self.editRuleButton.clicked.connect(self.edit_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))
|
ret.append(self.tr('Error while saving changes: ') + str(ex))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.tabWidget.isTabEnabled(self.tabs_indices["firewall"]):
|
if self.policyAllowRadioButton.isEnabled():
|
||||||
self.fw_model.apply_rules(self.policyAllowRadioButton.isChecked(),
|
self.fw_model.apply_rules(self.policyAllowRadioButton.isChecked(),
|
||||||
self.dnsCheckBox.isChecked(),
|
|
||||||
self.icmpCheckBox.isChecked(),
|
|
||||||
self.yumproxyCheckBox.isChecked(),
|
|
||||||
self.tempFullAccess.isChecked(),
|
self.tempFullAccess.isChecked(),
|
||||||
self.tempFullAccessTime.value())
|
self.tempFullAccessTime.value())
|
||||||
if self.fw_model.fw_changed:
|
if self.fw_model.fw_changed:
|
||||||
@ -757,114 +759,58 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
|
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
|
||||||
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
|
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
|
||||||
self.set_allow(model.allow)
|
self.set_allow(model.allow)
|
||||||
self.dnsCheckBox.setChecked(model.allowDns)
|
|
||||||
self.icmpCheckBox.setChecked(model.allowIcmp)
|
|
||||||
self.yumproxyCheckBox.setChecked(model.allowYumProxy)
|
|
||||||
if model.tempFullAccessExpireTime:
|
if model.tempFullAccessExpireTime:
|
||||||
self.tempFullAccess.setChecked(True)
|
self.tempFullAccess.setChecked(True)
|
||||||
self.tempFullAccessTime.setValue(
|
self.tempFullAccessTime.setValue(
|
||||||
(model.tempFullAccessExpireTime -
|
(model.tempFullAccessExpireTime -
|
||||||
int(datetime.datetime.now().strftime("%s")))/60)
|
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):
|
def set_allow(self, allow):
|
||||||
self.policyAllowRadioButton.setChecked(allow)
|
self.policyAllowRadioButton.setChecked(allow)
|
||||||
self.policyDenyRadioButton.setChecked(not allow)
|
self.policyDenyRadioButton.setChecked(not allow)
|
||||||
self.policy_changed(allow)
|
self.policy_changed(allow)
|
||||||
|
|
||||||
def policy_changed(self, checked):
|
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):
|
def new_rule_button_pressed(self):
|
||||||
dialog = NewFwRuleDlg()
|
dialog = NewFwRuleDlg()
|
||||||
self.run_rule_dialog(dialog)
|
self.fw_model.run_rule_dialog(dialog)
|
||||||
|
|
||||||
def edit_rule_button_pressed(self):
|
def edit_rule_button_pressed(self):
|
||||||
|
|
||||||
|
selected = self.rulesTreeView.selectedIndexes()
|
||||||
|
|
||||||
|
if len(selected) > 0:
|
||||||
dialog = NewFwRuleDlg()
|
dialog = NewFwRuleDlg()
|
||||||
dialog.set_ok_enabled(True)
|
dialog.set_ok_enabled(True)
|
||||||
selected = self.rulesTreeView.selectedIndexes()
|
|
||||||
if len(selected) > 0:
|
|
||||||
row = self.rulesTreeView.selectedIndexes().pop().row()
|
row = self.rulesTreeView.selectedIndexes().pop().row()
|
||||||
address = self.fw_model.get_column_string(0, row).replace(' ', '')
|
self.fw_model.populate_edit_dialog(dialog, row)
|
||||||
dialog.addressComboBox.setItemText(0, address)
|
self.fw_model.run_rule_dialog(dialog, row)
|
||||||
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)
|
|
||||||
|
|
||||||
def delete_rule_button_pressed(self):
|
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)
|
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:
|
# Bases on the original code by:
|
||||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||||
|
@ -31,10 +31,22 @@
|
|||||||
<property name="verticalSpacing">
|
<property name="verticalSpacing">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="0">
|
<item row="2" column="2">
|
||||||
<widget class="QLabel" name="label">
|
<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">
|
<property name="text">
|
||||||
<string>Protocol</string>
|
<string>UDP</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -45,13 +57,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -59,6 +64,31 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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">
|
<item row="0" column="1" colspan="3">
|
||||||
<widget class="QComboBox" name="addressComboBox">
|
<widget class="QComboBox" name="addressComboBox">
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
@ -66,6 +96,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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">
|
<item row="2" column="1">
|
||||||
<widget class="QRadioButton" name="tcp_radio">
|
<widget class="QRadioButton" name="tcp_radio">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -85,44 +122,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="2" column="0">
|
||||||
<widget class="QRadioButton" name="udp_radio">
|
<widget class="QLabel" name="label">
|
||||||
<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">
|
<property name="text">
|
||||||
<string>UDP</string>
|
<string>Protocol</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>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<locale language="English" country="UnitedStates"/>
|
<locale language="English" country="UnitedStates"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="basic_tab">
|
<widget class="QWidget" name="basic_tab">
|
||||||
<property name="locale">
|
<property name="locale">
|
||||||
@ -655,48 +655,101 @@
|
|||||||
<string>Firewall rules</string>
|
<string>Firewall rules</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_8">
|
<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">
|
<widget class="QRadioButton" name="policyAllowRadioButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Allow network access except...</string>
|
<string>Allow all outgoing Internet connections</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item>
|
||||||
<widget class="QCheckBox" name="icmpCheckBox">
|
<widget class="QRadioButton" name="policyDenyRadioButton">
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>323</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Allow ICMP traffic</string>
|
<string>Limit outgoing Internet connections to ...</string>
|
||||||
</property>
|
</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>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QRadioButton" name="policyDenyRadioButton">
|
<widget class="QLabel" name="firewalRulesLabel">
|
||||||
<property name="text">
|
<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>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QCheckBox" name="dnsCheckBox">
|
<widget class="QSpinBox" name="tempFullAccessTime">
|
||||||
<property name="text">
|
<property name="suffix">
|
||||||
<string>Allow DNS queries</string>
|
<string> min</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="value">
|
||||||
<bool>true</bool>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="2">
|
<item row="1" column="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_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">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetMaximumSize</enum>
|
<enum>QLayout::SetMaximumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -805,48 +858,57 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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">
|
<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">
|
<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>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="devices_tab">
|
<widget class="QWidget" name="devices_tab">
|
||||||
@ -1035,11 +1097,6 @@
|
|||||||
<tabstop>vcpus</tabstop>
|
<tabstop>vcpus</tabstop>
|
||||||
<tabstop>include_in_balancing</tabstop>
|
<tabstop>include_in_balancing</tabstop>
|
||||||
<tabstop>kernel</tabstop>
|
<tabstop>kernel</tabstop>
|
||||||
<tabstop>policyAllowRadioButton</tabstop>
|
|
||||||
<tabstop>policyDenyRadioButton</tabstop>
|
|
||||||
<tabstop>icmpCheckBox</tabstop>
|
|
||||||
<tabstop>dnsCheckBox</tabstop>
|
|
||||||
<tabstop>yumproxyCheckBox</tabstop>
|
|
||||||
<tabstop>newRuleButton</tabstop>
|
<tabstop>newRuleButton</tabstop>
|
||||||
<tabstop>rulesTreeView</tabstop>
|
<tabstop>rulesTreeView</tabstop>
|
||||||
<tabstop>editRuleButton</tabstop>
|
<tabstop>editRuleButton</tabstop>
|
||||||
|
Loading…
Reference in New Issue
Block a user