#include "stdafx.h" #include "OptionsWindow.h" #include "SandMan.h" #include "SettingsWindow.h" #include "TestProxyDialog.h" #include "../MiscHelpers/Common/Settings.h" #include "../MiscHelpers/Common/Common.h" #include "../MiscHelpers/Common/ComboInputDialog.h" #include "../MiscHelpers/Common/SettingsWidgets.h" #include "Helpers/WinAdmin.h" void COptionsWindow::CreateNetwork() { //connect(ui.chkBlockINet, SIGNAL(clicked(bool)), this, SLOT(OnBlockINet())); connect(ui.cmbBlockINet, SIGNAL(currentIndexChanged(int)), this, SLOT(OnBlockINet())); connect(ui.btnAddINetProg, SIGNAL(clicked(bool)), this, SLOT(OnAddINetProg())); connect(ui.btnDelINetProg, SIGNAL(clicked(bool)), this, SLOT(OnDelINetProg())); connect(ui.chkINetBlockPrompt, SIGNAL(clicked(bool)), this, SLOT(OnINetBlockChanged())); connect(ui.chkINetBlockMsg, SIGNAL(clicked(bool)), this, SLOT(OnINetBlockChanged())); connect(ui.treeINet, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnINetItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeINet, SIGNAL(itemSelectionChanged()), this, SLOT(OnINetSelectionChanged())); connect(ui.treeINet, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnINetChanged(QTreeWidgetItem *, int))); connect(ui.btnAddFwRule, SIGNAL(clicked(bool)), this, SLOT(OnAddNetFwRule())); connect(ui.btnDelFwRule, SIGNAL(clicked(bool)), this, SLOT(OnDelNetFwRule())); connect(ui.treeNetFw, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnNetFwItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeNetFw, SIGNAL(itemSelectionChanged()), this, SLOT(OnNetFwSelectionChanged())); connect(ui.treeNetFw, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnNetFwChanged(QTreeWidgetItem *, int))); connect(ui.btnAddDns, SIGNAL(clicked(bool)), this, SLOT(OnAddDnsFilter())); connect(ui.btnDelDns, SIGNAL(clicked(bool)), this, SLOT(OnDelDnsFilter())); ui.treeDns->setItemDelegateForColumn(0, new ProgramsDelegate(this, ui.treeDns, -1, this)); connect(ui.treeDns, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnDnsFilterChanged(QTreeWidgetItem *, int))); connect(ui.btnAddProxy, SIGNAL(clicked(bool)), this, SLOT(OnAddNetProxy())); connect(ui.btnDelProxy, SIGNAL(clicked(bool)), this, SLOT(OnDelNetProxy())); connect(ui.btnTestProxy, SIGNAL(clicked(bool)), this, SLOT(OnTestNetProxy())); connect(ui.btnMoveProxyUp, SIGNAL(clicked(bool)), this, SLOT(OnNetProxyMoveUp())); connect(ui.btnMoveProxyDown, SIGNAL(clicked(bool)), this, SLOT(OnNetProxyMoveDown())); connect(ui.chkProxyResolveHostnames, SIGNAL(clicked(bool)), this, SLOT(OnProxyResolveHostnames())); connect(ui.treeProxy, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnNetProxyItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeProxy, SIGNAL(itemSelectionChanged()), this, SLOT(OnNetProxySelectionChanged())); ui.treeProxy->setItemDelegateForColumn(0, new ProgramsDelegate(this, ui.treeProxy, -1, this)); connect(ui.treeProxy, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(OnNetProxyChanged(QTreeWidgetItem *, int))); connect(ui.chkShowNetFwTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowNetFwTmpl())); connect(ui.txtProgFwTest, SIGNAL(textChanged(const QString&)), this, SLOT(OnTestNetFwRule())); connect(ui.txtPortFwTest, SIGNAL(textChanged(const QString&)), this, SLOT(OnTestNetFwRule())); connect(ui.txtIPFwTest, SIGNAL(textChanged(const QString&)), this, SLOT(OnTestNetFwRule())); connect(ui.cmbProtFwTest, SIGNAL(currentIndexChanged(int)), this, SLOT(OnTestNetFwRule())); ui.cmbProtFwTest->addItem(tr("Any"), (int)eAny); ui.cmbProtFwTest->addItem(tr("TCP"), (int)eTcp); ui.cmbProtFwTest->addItem(tr("UDP"), (int)eUdp); ui.cmbProtFwTest->addItem(tr("ICMP"), (int)eIcmp); connect(ui.btnClearFwTest, SIGNAL(clicked(bool)), this, SLOT(OnClearNetFwTest())); connect(ui.chkBlockDns, SIGNAL(clicked(bool)), this, SLOT(OnBlockDns())); connect(ui.chkBlockSamba, SIGNAL(clicked(bool)), this, SLOT(OnBlockSamba())); connect(ui.tabsInternet, SIGNAL(currentChanged(int)), this, SLOT(OnInternetTab())); if (!CERT_IS_LEVEL(g_CertInfo, eCertAdvanced)) { ui.tabDNS->setEnabled(false); ui.tabNetProxy->setEnabled(false); } ui.chkProxyResolveHostnames->setVisible(false); } void COptionsWindow::OnBlockDns() { SetTemplate("BlockDNS", ui.chkBlockDns->isChecked()); } void COptionsWindow::OnBlockSamba() { SetTemplate("BlockPorts", ui.chkBlockSamba->isChecked()); } void COptionsWindow::LoadINetAccess() { // check if we are blocking globally and if so adapt the behaviour accordingly m_WFPisBlocking = !m_pBox->GetAPI()->GetGlobalSettings()->GetBool("AllowNetworkAccess", true); ui.lblNoWfp->setVisible(!theGUI->IsWFPEnabled()); // warn user that this is only user mode ui.cmbBlockINet->clear(); ui.cmbBlockINet->addItem(tr("Allow access"), 0); if (theGUI->IsWFPEnabled()) ui.cmbBlockINet->addItem(tr("Block using Windows Filtering Platform"), 1); ui.cmbBlockINet->addItem(tr("Block by denying access to Network devices"), 2); m_INetBlockChanged = false; } void COptionsWindow::SaveINetAccess() { int Mode = ui.cmbBlockINet->currentData().toInt(); if (Mode == 1) { if (!FindEntryInSettingList("AllowNetworkAccess", "!,n")) m_pBox->InsertText("AllowNetworkAccess", "!,n"); } else m_pBox->DelValue("AllowNetworkAccess", "!,n"); if (Mode == 0) { if (m_WFPisBlocking && !FindEntryInSettingList("AllowNetworkAccess", "y")) m_pBox->InsertText("AllowNetworkAccess", "y"); } else m_pBox->DelValue("AllowNetworkAccess", "y"); QTreeWidgetItem* pBlockedNet = FindGroupByName(""); if (pBlockedNet && pBlockedNet->childCount() > 0) { if (theGUI->IsWFPEnabled() && !FindEntryInSettingList("AllowNetworkAccess", ",n")) m_pBox->InsertText("AllowNetworkAccess", ",n"); } else m_pBox->DelValue("AllowNetworkAccess", ",n"); QTreeWidgetItem* pBlockedDev = FindGroupByName(""); if (pBlockedDev && pBlockedDev->childCount() > 0) SetAccessEntry(eFile, "", eClosed, "InternetAccessDevices"); else DelAccessEntry(eFile, "", eClosed, "InternetAccessDevices"); WriteAdvancedCheck(ui.chkINetBlockPrompt, "PromptForInternetAccess", "y", ""); WriteAdvancedCheck(ui.chkINetBlockMsg, "NotifyInternetAccessDenied", "", "n"); m_INetBlockChanged = false; } int COptionsWindow::GroupToINetMode(const QString& Mode) { if (Mode.compare("", Qt::CaseInsensitive) == 0) return 0; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 1; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 2; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 0 | 0x10; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 1 | 0x10; if (Mode.compare("", Qt::CaseInsensitive) == 0) return 2 | 0x10; return -1; } QString COptionsWindow::INetModeToGroup(int Mode) { switch (Mode) { case 0: return ""; case 1: return ""; case 2: return ""; case 0 | 0x10: return ""; case 1 | 0x10: return ""; case 2 | 0x10: return ""; } return ""; } void COptionsWindow::LoadBlockINet() { if (IsAccessEntrySet(eFile, "!", eClosed, "InternetAccessDevices")) ui.cmbBlockINet->setCurrentIndex(ui.cmbBlockINet->findData(2)); else if (theGUI->IsWFPEnabled() && (FindEntryInSettingList("AllowNetworkAccess", "!,n") || (m_WFPisBlocking && !FindEntryInSettingList("AllowNetworkAccess", "y")))) ui.cmbBlockINet->setCurrentIndex(ui.cmbBlockINet->findData(1)); else ui.cmbBlockINet->setCurrentIndex(ui.cmbBlockINet->findData(0)); //ui.chkBlockINet->setChecked(); //ui.chkINetBlockPrompt->setEnabled(ui.chkBlockINet->isChecked()); ui.chkINetBlockPrompt->setEnabled(ui.cmbBlockINet->currentIndex() != 0); ui.chkINetBlockPrompt->setChecked(m_pBox->GetBool("PromptForInternetAccess", false)); //ui.chkINetBlockMsg->setEnabled(ui.chkBlockINet->isChecked()); ui.chkINetBlockMsg->setEnabled(ui.cmbBlockINet->currentIndex() != 0); ui.chkINetBlockMsg->setChecked(m_pBox->GetBool("NotifyInternetAccessDenied", true)); ui.treeINet->clear(); for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { QTreeWidgetItem* pGroupItem = ui.treeGroups->topLevelItem(i); int GroupMode = GroupToINetMode(pGroupItem->data(0, Qt::UserRole).toString()); if (GroupMode == -1) continue; for (int j = 0; j < pGroupItem->childCount(); j++) { QString Value = pGroupItem->child(j)->data(0, Qt::UserRole).toString(); QTreeWidgetItem* pItem = new QTreeWidgetItem(); pItem->setCheckState(0, (GroupMode & 0x10) != 0 ? Qt::Unchecked : Qt::Checked); int Mode = GroupMode & ~0x10; SetProgramItem(Value, pItem, 0); pItem->setData(1, Qt::UserRole, Mode); if (!theGUI->IsWFPEnabled() && Mode == 1) Mode = -1; // this mode is not available pItem->setText(1, GetINetModeStr(Mode)); ui.treeINet->addTopLevelItem(pItem); } } ui.chkBlockDns->setChecked(m_BoxTemplates.contains("BlockDNS")); ui.chkBlockSamba->setChecked(m_BoxTemplates.contains("BlockPorts")); } QString COptionsWindow::GetINetModeStr(int Mode) { switch (Mode) { case 0: return tr("Allow"); case 1: return tr("Block (WFP)"); // Windows Filtering Platform case 2: return tr("Block (NDev)"); // Network Devices } return tr(""); } void COptionsWindow::OnINetItemDoubleClicked(QTreeWidgetItem* pItem, int Column) { QString Program = pItem->data(0, Qt::UserRole).toString(); //QWidget* pProgram = new QWidget(); //pProgram->setAutoFillBackground(true); //QHBoxLayout* pLayout = new QHBoxLayout(); //pLayout->setContentsMargins(0,0,0,0); //pLayout->setSpacing(0); //pProgram->setLayout(pLayout); //QComboBox* pCombo = new QComboBox(pProgram); QComboBox* pCombo = new QComboBox(); for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); pCombo->addItem(tr("Group: %1").arg(pItem->text(0)), pItem->data(0, Qt::UserRole).toString()); } foreach(const QString & Name, m_Programs) pCombo->addItem(Name, Name); pCombo->setEditable(true); int Index = pCombo->findData(Program); pCombo->setCurrentIndex(Index); if(Index == -1) pCombo->setCurrentText(Program); //pLayout->addWidget(pCombo); //ui.treeINet->setItemWidget(pItem, 0, pProgram); ui.treeINet->setItemWidget(pItem, 0, pCombo); QComboBox* pMode = new QComboBox(); for (int i = 0; i < 3; i++) { if (!theGUI->IsWFPEnabled() && i == 1) continue; // this mode is not available pMode->addItem(GetINetModeStr(i), i); } pMode->setCurrentIndex(pMode->findData(pItem->data(1, Qt::UserRole))); ui.treeINet->setItemWidget(pItem, 1, pMode); } void COptionsWindow::OnINetChanged(QTreeWidgetItem* pItem, int Column) { if (Column != 0) return; if (pItem->checkState(0) == Qt::Checked) { QString Program = pItem->data(0, Qt::UserRole).toString(); int Mode = pItem->data(1, Qt::UserRole).toInt(); Mode |= 0x10; if (DelProgramFromGroup(Program, INetModeToGroup(Mode))) { Mode &= ~0x10; AddProgramToGroup(Program, INetModeToGroup(Mode)); } } else { QString Program = pItem->data(0, Qt::UserRole).toString(); int Mode = pItem->data(1, Qt::UserRole).toInt(); Mode &= ~0x10; if (DelProgramFromGroup(Program, INetModeToGroup(Mode))) { Mode |= 0x10; AddProgramToGroup(Program, INetModeToGroup(Mode)); } } m_INetBlockChanged = true; OnOptChanged(); } void COptionsWindow::CloseINetEdit(bool bSave) { for (int i = 0; i < ui.treeINet->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeINet->topLevelItem(i); CloseINetEdit(pItem, bSave); } } void COptionsWindow::CloseINetEdit(QTreeWidgetItem* pItem, bool bSave) { QWidget* pProgram = ui.treeINet->itemWidget(pItem, 0); if (!pProgram) return; if (bSave) { //QHBoxLayout* pLayout = (QHBoxLayout*)pProgram->layout(); //QComboBox* pCombo = (QComboBox*)pLayout->itemAt(0)->widget(); QComboBox* pCombo = (QComboBox*)pProgram; QComboBox* pMode = (QComboBox*)ui.treeINet->itemWidget(pItem, 1); QString OldProgram = pItem->data(0, Qt::UserRole).toString(); int OldMode = pItem->data(1, Qt::UserRole).toInt(); if (pItem->checkState(0) == Qt::Unchecked) OldMode |= 0x10; DelProgramFromGroup(OldProgram, INetModeToGroup(OldMode)); QString NewProgram = pCombo->currentText(); if (NewProgram.isEmpty()) { QMessageBox::warning(this, "SandboxiePlus", tr("A non empty program name is required.")); return; } int NewMode = pMode->currentData().toInt(); if (pItem->checkState(0) == Qt::Unchecked) NewMode |= 0x10; AddProgramToGroup(NewProgram, INetModeToGroup(NewMode)); SetProgramItem(NewProgram, pItem, 0); pItem->setText(1, GetINetModeStr(NewMode)); pItem->setData(1, Qt::UserRole, NewMode); m_INetBlockChanged = true; OnOptChanged(); } ui.treeINet->setItemWidget(pItem, 0, NULL); ui.treeINet->setItemWidget(pItem, 1, NULL); } void COptionsWindow::OnBlockINet() { if (m_HoldChange) return; //bool Enable = ui.chkBlockINet->isChecked(); int Mode = ui.cmbBlockINet->currentData().toInt(); ui.chkINetBlockPrompt->setEnabled(Mode != 0); ui.chkINetBlockMsg->setEnabled(Mode != 0); if (Mode == 2) SetAccessEntry(eFile, "!", eClosed, "InternetAccessDevices"); else DelAccessEntry(eFile, "!", eClosed, "InternetAccessDevices"); m_INetBlockChanged = true; OnOptChanged(); } void COptionsWindow::OnAddINetProg() { QString Value = SelectProgram(); if (Value.isEmpty()) return; int Mode = 0; QTreeWidgetItem* pItem = new QTreeWidgetItem(); SetProgramItem(Value, pItem, 0); pItem->setText(1, GetINetModeStr(Mode)); pItem->setData(1, Qt::UserRole, Mode); pItem->setCheckState(0, Qt::Checked); ui.treeINet->addTopLevelItem(pItem); AddProgramToGroup(Value, INetModeToGroup(Mode)); m_INetBlockChanged = true; OnOptChanged(); } void COptionsWindow::OnDelINetProg() { QTreeWidgetItem* pItem = ui.treeINet->currentItem(); if (!pItem) return; QString OldProgram = pItem->data(0, Qt::UserRole).toString(); int OldMode = pItem->data(1, Qt::UserRole).toInt(); if (pItem->checkState(0) == Qt::Unchecked) OldMode |= 0x10; DelProgramFromGroup(OldProgram, INetModeToGroup(OldMode)); delete pItem; m_INetBlockChanged = true; OnOptChanged(); } bool COptionsWindow::FindEntryInSettingList(const QString& Name, const QString& Value) { QStringList Settings = m_pBox->GetTextList(Name, false); foreach(const QString & Setting, Settings) { if (Setting.compare(Value, Qt::CaseInsensitive) == 0) return true; } return false; } void COptionsWindow::LoadNetFwRules() { ui.treeNetFw->clear(); foreach(const QString & Value, m_pBox->GetTextList("NetworkAccess", m_Template)) ParseAndAddFwRule(Value); foreach(const QString & Value, m_pBox->GetTextList("NetworkAccessDisabled", m_Template)) ParseAndAddFwRule(Value, true); LoadNetFwRulesTmpl(); m_NetFwRulesChanged = false; } void COptionsWindow::LoadNetFwRulesTmpl(bool bUpdate) { if (ui.chkShowNetFwTmpl->isChecked()) { foreach(const QString& Template, m_pBox->GetTemplates()) { foreach(const QString& Value, m_pBox->GetTextListTmpl("NetworkAccess", Template)) ParseAndAddFwRule(Value, false, Template); } } else if (bUpdate) { for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); ) { QTreeWidgetItem* pItem = ui.treeNetFw->topLevelItem(i); int Type = pItem->data(1, Qt::UserRole).toInt(); if (Type == -1) { delete pItem; continue; // entry from template } i++; } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Firewall // COptionsWindow::ENetWfAction COptionsWindow::GetFwRuleAction(const QString& Value) { if (Value.compare("Allow", Qt::CaseInsensitive) == 0) return eAllow; //if (Value.compare("Block", Qt::CaseInsensitive) == 0) return eBlock; } QString COptionsWindow::GetFwRuleActionStr(ENetWfAction Action) { switch (Action) { case eAllow: return "Allow"; case eBlock: return "Block"; } return ""; } COptionsWindow::ENetWfProt COptionsWindow::GetFwRuleProt(const QString& Value) { if (Value.compare("TCP", Qt::CaseInsensitive) == 0) return eTcp; if (Value.compare("UDP", Qt::CaseInsensitive) == 0) return eUdp; if (Value.compare("ICMP", Qt::CaseInsensitive) == 0) return eIcmp; return eAny; } void COptionsWindow::ParseAndAddFwRule(const QString& Value, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); //NetworkAccess=explorer.exe,Allow;Port=137,138,139,445;Address=192.168.0.1-192.168.100.255;Protocol=TCP; QString FirstStr; TArguments Tags = GetArguments(Value, L';', L'=', &FirstStr, true); StrPair ProgAction = Split2(FirstStr, ",", true); QString Program = ProgAction.second.isEmpty() ? "" : ProgAction.first; QString Action = ProgAction.second.isEmpty() ? ProgAction.first : ProgAction.second; pItem->setData(0, Qt::UserRole, Program); bool bAll = Program.isEmpty() || Program == "*"; if (bAll) Program = tr("All Programs"); bool Not = Program.left(1) == "!"; if (Not) Program.remove(0, 1); if (Program.left(1) == "<") Program = tr("Group: %1").arg(Program.mid(1, Program.length() - 2)); else if(!bAll) m_Programs.insert(Program); pItem->setText(0, (Not ? "NOT " : "") + Program); pItem->setText(1, Action + (Template.isEmpty() ? "" : " (" + Template + ")")); pItem->setData(1, Qt::UserRole, Template.isEmpty() ? (int)GetFwRuleAction(Action) : -1); QString Port = Tags.value("port"); pItem->setText(2, Port); pItem->setData(2, Qt::UserRole, Port); QString IP = Tags.value("address"); pItem->setText(3, IP); pItem->setData(3, Qt::UserRole, IP); QString Prot = Tags.value("protocol"); pItem->setText(4, Prot); pItem->setData(4, Qt::UserRole, (int)GetFwRuleProt(Prot)); if(Template.isEmpty()) pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); ui.treeNetFw->addTopLevelItem(pItem); } void COptionsWindow::SaveNetFwRules() { QList Rules; QList RulesDisabled; for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeNetFw->topLevelItem(i); int Type = pItem->data(1, Qt::UserRole).toInt(); if (Type == -1) continue; // entry from template QString Program = pItem->data(0, Qt::UserRole).toString(); ENetWfAction Action = (ENetWfAction)pItem->data(1, Qt::UserRole).toInt(); QString Port = pItem->data(2, Qt::UserRole).toString(); QString IP = pItem->data(3, Qt::UserRole).toString(); QString Prot = pItem->text(4); QString Temp = GetFwRuleActionStr(Action); //if (Program.contains("=") || Program.contains(";") || Program.contains(",")) // todo: make SBIE parses this properly // Program = "\'" + Program + "\'"; if (Program.isEmpty()) Program = "*"; Temp.prepend(Program + ","); QStringList Tags = QStringList(Temp); if (!Port.isEmpty()) Tags.append("Port=" + Port); if (!IP.isEmpty()) Tags.append("Address=" + IP); if (!Prot.isEmpty()) Tags.append("Protocol=" + Prot); if(pItem->checkState(0) == Qt::Checked) Rules.append(Tags.join(";")); else RulesDisabled.append(Tags.join(";")); } WriteTextList("NetworkAccess", Rules); WriteTextList("NetworkAccessDisabled", RulesDisabled); m_NetFwRulesChanged = false; } void COptionsWindow::OnNetFwItemDoubleClicked(QTreeWidgetItem* pItem, int Column) { int Action = pItem->data(1, Qt::UserRole).toInt(); if (Action == -1) { QMessageBox::warning(this, "SandboxiePlus", tr("Template values can not be edited.")); return; } QString Program = pItem->data(0, Qt::UserRole).toString(); QWidget* pProgram = new QWidget(); pProgram->setAutoFillBackground(true); QHBoxLayout* pLayout = new QHBoxLayout(); pLayout->setContentsMargins(0,0,0,0); pLayout->setSpacing(0); pProgram->setLayout(pLayout); QToolButton* pNot = new QToolButton(pProgram); pNot->setText("!"); pNot->setCheckable(true); if (Program.left(1) == "!"){ pNot->setChecked(true); Program.remove(0, 1); } pLayout->addWidget(pNot); QComboBox* pCombo = new QComboBox(pProgram); pCombo->addItem(tr("All Programs"), ""); for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); pCombo->addItem(tr("Group: %1").arg(pItem->text(0)), pItem->data(0, Qt::UserRole).toString()); } foreach(const QString & Name, m_Programs) pCombo->addItem(Name, Name); pCombo->setEditable(true); int Index = pCombo->findData(Program); pCombo->setCurrentIndex(Index); if(Index == -1) pCombo->setCurrentText(Program); pLayout->addWidget(pCombo); ui.treeNetFw->setItemWidget(pItem, 0, pProgram); QComboBox* pMode = new QComboBox(); pMode->addItem(tr("Allow"), (int)eAllow); pMode->addItem(tr("Block"), (int)eBlock); pMode->setCurrentIndex(pMode->findData(pItem->data(1, Qt::UserRole))); ui.treeNetFw->setItemWidget(pItem, 1, pMode); QLineEdit* pPort = new QLineEdit(); pPort->setText(pItem->data(2, Qt::UserRole).toString()); ui.treeNetFw->setItemWidget(pItem, 2, pPort); QLineEdit* pIP = new QLineEdit(); pIP->setText(pItem->data(3, Qt::UserRole).toString()); ui.treeNetFw->setItemWidget(pItem, 3, pIP); QComboBox* pProt = new QComboBox(); pProt->addItem(tr("Any"), (int)eAny); pProt->addItem(tr("TCP"), (int)eTcp); pProt->addItem(tr("UDP"), (int)eUdp); pProt->addItem(tr("ICMP"), (int)eIcmp); pProt->setCurrentIndex(pProt->findData(pItem->data(4, Qt::UserRole))); ui.treeNetFw->setItemWidget(pItem, 4, pProt); } void COptionsWindow::OnNetFwChanged(QTreeWidgetItem* pItem, int Column) { if (Column != 0) return; m_NetFwRulesChanged = true; OnOptChanged(); } void COptionsWindow::CloseNetFwEdit(bool bSave) { for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeNetFw->topLevelItem(i); CloseNetFwEdit(pItem, bSave); } } void COptionsWindow::CloseNetFwEdit(QTreeWidgetItem* pItem, bool bSave) { QWidget* pProgram = ui.treeNetFw->itemWidget(pItem, 0); if (!pProgram) return; if (bSave) { QHBoxLayout* pLayout = (QHBoxLayout*)pProgram->layout(); QToolButton* pNot = (QToolButton*)pLayout->itemAt(0)->widget(); QComboBox* pCombo = (QComboBox*)pLayout->itemAt(1)->widget(); QComboBox* pAction = (QComboBox*)ui.treeNetFw->itemWidget(pItem, 1); QLineEdit* pPort = (QLineEdit*)ui.treeNetFw->itemWidget(pItem, 2); QLineEdit* pIP = (QLineEdit*)ui.treeNetFw->itemWidget(pItem, 3); QComboBox* pProt = (QComboBox*)ui.treeNetFw->itemWidget(pItem, 4); QString Program = pCombo->currentText(); int Index = pCombo->findText(Program); if (Index != -1) Program = pCombo->itemData(Index, Qt::UserRole).toString(); pItem->setText(0, (pNot->isChecked() ? "NOT " : "") + pCombo->currentText()); pItem->setData(0, Qt::UserRole, (pNot->isChecked() ? "!" : "") + Program); pItem->setText(1, pAction->currentText()); pItem->setData(1, Qt::UserRole, pAction->currentData()); pItem->setText(2, pPort->text()); pItem->setData(2, Qt::UserRole, pPort->text()); pItem->setText(3, pIP->text()); pItem->setData(3, Qt::UserRole, pIP->text()); pItem->setText(4, pProt->currentText()); pItem->setData(4, Qt::UserRole, pProt->currentData()); m_NetFwRulesChanged = true; OnOptChanged(); } for (int i = 0; i < 5; i++) ui.treeNetFw->setItemWidget(pItem, i, NULL); } void COptionsWindow::OnAddNetFwRule() { QTreeWidgetItem* pItem = new QTreeWidgetItem(); pItem->setData(0, Qt::UserRole, ""); pItem->setText(0, tr("All Programs")); pItem->setText(1, GetFwRuleActionStr(eBlock)); pItem->setData(1, Qt::UserRole, (int)eBlock); pItem->setCheckState(0, Qt::Checked); ui.treeNetFw->addTopLevelItem(pItem); m_NetFwRulesChanged = true; OnOptChanged(); } void COptionsWindow::OnDelNetFwRule() { QTreeWidgetItem* pItem = ui.treeNetFw->currentItem(); if (!pItem) return; delete pItem; m_NetFwRulesChanged = true; OnOptChanged(); } // dns void COptionsWindow::LoadDnsFilter() { ui.treeDns->clear(); foreach(const QString & Value, m_pBox->GetTextList("NetworkDnsFilter", m_Template)) AddDnsFilter(Value); foreach(const QString& Value, m_pBox->GetTextList("NetworkDnsFilterDisabled", m_Template)) AddDnsFilter(Value, true); m_DnsFilterChanged = false; } void COptionsWindow::AddDnsFilter(const QString& Value, bool disabled, const QString& Template) { StrPair ProgDns = Split2(Value, ","); if (ProgDns.second.isEmpty()) { ProgDns.second = ProgDns.first; ProgDns.first = ""; } StrPair DomainIP = Split2(ProgDns.second, ":"); AddDnsFilter(ProgDns.first, DomainIP.first, SplitStr(DomainIP.second, ";"), disabled, Template); } void COptionsWindow::AddDnsFilter(const QString& Prog, const QString& Domain, const QStringList& IPs, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); pItem->setData(1, Qt::UserRole, Template.isEmpty() ? 0 : -1); SetProgramItem(Prog, pItem, 0, (Template.isEmpty() ? "" : " (" + Template + ")")); if(Template.isEmpty()) pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); pItem->setText(1, Domain); pItem->setText(2, IPs.join(";")); ui.treeDns->addTopLevelItem(pItem); } void COptionsWindow::SaveDnsFilter() { QStringList NetworkDnsFilter; QStringList NetworkDnsFilterDisabled; for (int i = 0; i < ui.treeDns->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeDns->topLevelItem(i); int Type = pItem->data(1, Qt::UserRole).toInt(); if (Type == -1) continue; // entry from template QString Prog = pItem->data(0, Qt::UserRole).toString(); QString Domain = pItem->text(1); QString IPs = pItem->text(2); QString Entry = Domain; if (!IPs.isEmpty()) Entry.append(":" + IPs); if (!Prog.isEmpty()) Entry.prepend(Prog + ","); if (pItem->checkState(0) == Qt::Checked) NetworkDnsFilter.append(Entry); else NetworkDnsFilterDisabled.append(Entry); } WriteTextList("NetworkDnsFilter", NetworkDnsFilter); WriteTextList("NetworkDnsFilterDisabled", NetworkDnsFilterDisabled); m_DnsFilterChanged = false; } void COptionsWindow::OnAddDnsFilter() { QString Domain = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a domain to be filtered")); if (Domain.isEmpty()) return; AddDnsFilter("", Domain); m_DnsFilterChanged = true; OnOptChanged(); } void COptionsWindow::OnDelDnsFilter() { DeleteAccessEntry(ui.treeDns->currentItem(), 1); m_DnsFilterChanged = true; OnOptChanged(); } // // proxy COptionsWindow::EAuthMode COptionsWindow::GetAuthMode(const QString& Value) { if (Value.compare("Yes", Qt::CaseInsensitive) == 0) return eAuthEnabled; return eAuthDisabled; } QString COptionsWindow::GetAuthModeStr(COptionsWindow::EAuthMode Mode) { switch (Mode) { case eAuthEnabled: return tr("Yes"); case eAuthDisabled: return tr("No"); } return ""; } void COptionsWindow::OnProxyResolveHostnames() { m_NetProxyChanged = true; OnOptChanged(); } void COptionsWindow::OnTestNetProxy() { QTreeWidgetItem* pItem = ui.treeProxy->currentItem(); if (!pItem) return; QString IP = pItem->data(1, Qt::UserRole).toString(); QString Port = pItem->data(2, Qt::UserRole).toString(); EAuthMode AuthMode = (EAuthMode)pItem->data(3, Qt::UserRole).toInt(); QString Login = pItem->data(4, Qt::UserRole).toString(); QString Pass = pItem->data(5, Qt::UserRole).toString(); if (IP.isEmpty() || Port.isEmpty()) { QMessageBox::warning(this, "SandboxiePlus", tr("Please enter IP and Port.")); return; } CTestProxyDialog* dialog = new CTestProxyDialog(IP, Port, AuthMode, Login, Pass, this); dialog->show(); } void COptionsWindow::OnNetProxyMoveUp() { QTreeWidgetItem* pItem = ui.treeProxy->currentItem(); if (!pItem) return; int Index = ui.treeProxy->indexOfTopLevelItem(pItem); if (Index == 0) return; ui.treeProxy->takeTopLevelItem(Index); ui.treeProxy->insertTopLevelItem(Index - 1, pItem); ui.treeProxy->setCurrentItem(pItem); m_NetProxyChanged = true; OnOptChanged(); } void COptionsWindow::OnNetProxyMoveDown() { QTreeWidgetItem* pItem = ui.treeProxy->currentItem(); if (!pItem) return; int Index = ui.treeProxy->indexOfTopLevelItem(pItem); if (Index == ui.treeProxy->topLevelItemCount() - 1) return; ui.treeProxy->takeTopLevelItem(Index); ui.treeProxy->insertTopLevelItem(Index + 1, pItem); ui.treeProxy->setCurrentItem(pItem); m_NetProxyChanged = true; OnOptChanged(); } void COptionsWindow::OnNetProxyItemDoubleClicked(QTreeWidgetItem* pItem, int Column) { QString Program = pItem->data(0, Qt::UserRole).toString(); QWidget* pProgram = new QWidget(); pProgram->setAutoFillBackground(true); QHBoxLayout* pLayout = new QHBoxLayout(); pLayout->setContentsMargins(0, 0, 0, 0); pLayout->setSpacing(0); pProgram->setLayout(pLayout); QComboBox* pCombo = new QComboBox(pProgram); pCombo->addItem(tr("All Programs"), ""); foreach(const QString & Name, m_Programs) pCombo->addItem(Name, Name); pCombo->setEditable(true); int Index = pCombo->findData(Program); pCombo->setCurrentIndex(Index); if (Index == -1) pCombo->setCurrentText(Program); pLayout->addWidget(pCombo); ui.treeProxy->setItemWidget(pItem, 0, pProgram); QLineEdit* pIP = new QLineEdit(); pIP->setText(pItem->data(1, Qt::UserRole).toString()); ui.treeProxy->setItemWidget(pItem, 1, pIP); QLineEdit* pPort = new QLineEdit(); pPort->setText(pItem->data(2, Qt::UserRole).toString()); ui.treeProxy->setItemWidget(pItem, 2, pPort); QComboBox* pAuth = new QComboBox(); pAuth->addItem(GetAuthModeStr(eAuthEnabled), (int)eAuthEnabled); pAuth->addItem(GetAuthModeStr(eAuthDisabled), (int)eAuthDisabled); pAuth->setCurrentIndex(pAuth->findData(pItem->data(3, Qt::UserRole))); ui.treeProxy->setItemWidget(pItem, 3, pAuth); QLineEdit* pLogin = new QLineEdit(); pLogin->setMaxLength(255); pLogin->setText(pItem->data(4, Qt::UserRole).toString()); ui.treeProxy->setItemWidget(pItem, 4, pLogin); QLineEdit* pPass = new QLineEdit(); pPass->setMaxLength(255); pPass->setText(pItem->data(5, Qt::UserRole).toString()); ui.treeProxy->setItemWidget(pItem, 5, pPass); } void COptionsWindow::LoadNetProxy() { //ui.chkProxyResolveHostnames->setChecked(m_pBox->GetBool("NetworkProxyResolveHostnames", false)); ui.treeProxy->clear(); foreach(const QString & Value, m_pBox->GetTextList("NetworkUseProxy", m_Template)) ParseAndAddNetProxy(Value); foreach(const QString & Value, m_pBox->GetTextList("NetworkUseProxyDisabled", m_Template)) ParseAndAddNetProxy(Value, true); m_NetProxyChanged = false; } void COptionsWindow::ParseAndAddNetProxy(const QString& Value, bool disabled, const QString& Template) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); // NetworkUseProxy=explorer.exe,Address=192.168.0.1;Port=5000;Auth=Yes;Login=login;Password=pass StrPair ProgProxy = Split2(Value, ","); QString Proxy = ProgProxy.second.isEmpty() ? ProgProxy.first : ProgProxy.second; QString Program = ProgProxy.second.isEmpty() ? "*" : ProgProxy.first; TArguments Tags = GetArguments(Proxy, L';', L'=', NULL, true); pItem->setCheckState(0, disabled ? Qt::Unchecked : Qt::Checked); SetProgramItem(Program, pItem, 0, (Template.isEmpty() ? "" : " (" + Template + ")")); QString IP = Tags.value("address"); pItem->setText(1, IP); pItem->setData(1, Qt::UserRole, IP); QString Port = Tags.value("port"); pItem->setText(2, Port); pItem->setData(2, Qt::UserRole, Port); QString Auth = Tags.value("auth"); pItem->setText(3, Auth); pItem->setData(3, Qt::UserRole, (int)GetAuthMode(Auth)); QString Login = Tags.value("login"); if (Login.length() > 255) Login = Login.left(255); pItem->setText(4, Login); pItem->setData(4, Qt::UserRole, Login); QString Pass = Tags.value("password"); if(Pass.isEmpty()) { Pass = Tags.value("encryptedpw"); auto res = theAPI->RC4Crypt(QByteArray::fromBase64(Pass.toLatin1())); if (!res.IsError()) Pass = QString::fromWCharArray((wchar_t*)res.GetValue().data(), res.GetValue().length() / sizeof(wchar_t)); } if (Pass.length() > 255) Pass = Pass.left(255); pItem->setText(5, Pass); pItem->setData(5, Qt::UserRole, Pass); if(Template.isEmpty()) pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); ui.treeProxy->addTopLevelItem(pItem); } void COptionsWindow::SaveNetProxy() { //WriteAdvancedCheck(ui.chkProxyResolveHostnames, "NetworkProxyResolveHostnames", "y", ""); QStringList NetworkUseProxy; QStringList NetworkUseProxyDisabled; for (int i = 0; i < ui.treeProxy->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeProxy->topLevelItem(i); QString Program = pItem->data(0, Qt::UserRole).toString(); QString IP = pItem->data(1, Qt::UserRole).toString(); QString Port = pItem->data(2, Qt::UserRole).toString(); int iAuth = pItem->data(3, Qt::UserRole).toInt(); QString Login = pItem->data(4, Qt::UserRole).toString(); QString Pass = pItem->data(5, Qt::UserRole).toString(); if (IP.isEmpty() || Port.isEmpty()) { QMessageBox::warning(this, "SandboxiePlus", QString::number(i + 1) + tr(" entry: IP or Port cannot be empty")); continue; } QStringList Tags; if (Program.isEmpty()) Program = "*"; Tags.append("Address=" + IP); Tags.append("Port=" + Port); switch (iAuth) { case eAuthEnabled: Tags.append("Auth=Yes"); break; case eAuthDisabled: Tags.append("Auth=No"); break; } if (!Login.isEmpty()) Tags.append("Login=" + Login); if (!Pass.isEmpty()) { auto res = theAPI->RC4Crypt(QByteArray((char*)Pass.toStdWString().c_str(), Pass.length() * sizeof(wchar_t))); if(res.IsError()) Tags.append("Password=" + Pass); else Tags.append("EncryptedPW=" + res.GetValue().toBase64(QByteArray::OmitTrailingEquals)); } QString Entry = Tags.join(";").prepend(Program + ","); if (pItem->checkState(0) == Qt::Checked) NetworkUseProxy.append(Entry); else NetworkUseProxyDisabled.append(Entry); } WriteNetProxy("NetworkUseProxy", NetworkUseProxy); WriteNetProxy("NetworkUseProxyDisabled", NetworkUseProxyDisabled); m_NetProxyChanged = false; } void COptionsWindow::WriteNetProxy(const QString& Setting, const QStringList& List) { m_pBox->DelValue(Setting); foreach(const QString& Value, List) m_pBox->AppendText(Setting, Value); } void COptionsWindow::CloseNetProxyEdit(bool bSave) { for (int i = 0; i < ui.treeProxy->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeProxy->topLevelItem(i); CloseNetProxyEdit(pItem, bSave); } } void COptionsWindow::CloseNetProxyEdit(QTreeWidgetItem* pItem, bool bSave) { QWidget* pProgram = ui.treeProxy->itemWidget(pItem, 0); if (!pProgram) return; if (bSave) { QHBoxLayout* pLayout = (QHBoxLayout*)pProgram->layout(); QComboBox* pCombo = (QComboBox*)pLayout->itemAt(0)->widget(); QLineEdit* pIP = (QLineEdit*)ui.treeProxy->itemWidget(pItem, 1); QLineEdit* pPort = (QLineEdit*)ui.treeProxy->itemWidget(pItem, 2); QComboBox* pAuth = (QComboBox*)ui.treeProxy->itemWidget(pItem, 3); QLineEdit* pLogin = (QLineEdit*)ui.treeProxy->itemWidget(pItem, 4); QLineEdit* pPass = (QLineEdit*)ui.treeProxy->itemWidget(pItem, 5); QString Program = pCombo->currentText(); int Index = pCombo->findText(Program); if (Index != -1) Program = pCombo->itemData(Index, Qt::UserRole).toString(); pItem->setText(0, pCombo->currentText()); pItem->setData(0, Qt::UserRole, Program); pItem->setText(1, pIP->text()); pItem->setData(1, Qt::UserRole, pIP->text()); pItem->setText(2, pPort->text()); pItem->setData(2, Qt::UserRole, pPort->text()); pItem->setText(3, pAuth->currentText()); pItem->setData(3, Qt::UserRole, pAuth->currentData()); pItem->setText(4, pLogin->text()); pItem->setData(4, Qt::UserRole, pLogin->text()); pItem->setText(5, pPass->text()); pItem->setData(5, Qt::UserRole, pPass->text()); m_NetProxyChanged = true; OnOptChanged(); } for (int i = 0; i < 6; i++) ui.treeProxy->setItemWidget(pItem, i, NULL); } void COptionsWindow::OnAddNetProxy() { QTreeWidgetItem* pItem = new QTreeWidgetItem(); pItem->setData(0, Qt::UserRole, ""); pItem->setText(0, tr("All Programs")); pItem->setData(1, Qt::UserRole, "192.0.2.0"); pItem->setText(1, "192.0.2.0"); pItem->setData(2, Qt::UserRole, "24"); pItem->setText(2, "24"); pItem->setData(3, Qt::UserRole, (int)eAuthDisabled); pItem->setText(3, GetAuthModeStr(eAuthDisabled)); pItem->setCheckState(0, Qt::Checked); ui.treeProxy->addTopLevelItem(pItem); m_NetProxyChanged = true; OnOptChanged(); } void COptionsWindow::OnDelNetProxy() { DeleteAccessEntry(ui.treeProxy->currentItem(), 1); m_NetProxyChanged = true; OnOptChanged(); } // void COptionsWindow__SetRowColor(QTreeWidgetItem* pItem, bool bMatch, bool bConflict = false, bool bBlock = false, bool bActive = false) { #define setColor(i, b) theGUI->m_DarkTheme ? pItem->setForeground(i, b) : pItem->setBackground(i, b) for (int i = 0; i < pItem->columnCount(); i++) { if (!bMatch) { setColor(i, Qt::white); } else if(bConflict) setColor(i, QColor(255, 255, 0)); // yellow else if (!bBlock) { if (bActive) setColor(i, QColor(128, 255, 128)); // dark green else setColor(i, QColor(224, 240, 224)); // light green } else { if (bActive) setColor(i, QColor(255, 128, 128)); // dark red else setColor(i, QColor(240, 224, 224)); // light red } } } struct SFirewallRule { enum EMatch { eNone = 0, eGlobal, eByNot, eByRange, eExact }; EMatch MatchProg(const QString& TestProg) { if (Program.isEmpty()) return eGlobal; QString Test = Program; bool bNot = false; if (Test.left(1) == "!") { Test.remove(0, 1); bNot = true; } // ToDo: match groups and wildcards if (TestProg.isEmpty() || ((Test.compare(TestProg, Qt::CaseInsensitive) == 0) != bNot)) return bNot ? eByNot : eExact; return eNone; } void SetPorts(const QString& Ports) { PortMap.clear(); QStringList PortList = SplitStr(Ports, ","); foreach(const QString & Port, PortList) { StrPair BeginEnd = Split2(Port, "-"); quint16 Begin = BeginEnd.first.toInt(); quint16 End = BeginEnd.second.isEmpty() ? Begin : BeginEnd.second.toInt(); PortMap.insert(End, Begin); } } EMatch MatchPort(quint16 TestPort) { if (PortMap.isEmpty()) return eGlobal; if (TestPort == 0) return eExact; auto I = PortMap.lowerBound(TestPort); if (I == PortMap.end()) return eNone; if (I.key() < TestPort) return eNone; if (TestPort < I.value()) return eNone; return I.key() == I.value() ? eExact : eByRange; } void SetAddresses(const QString& Addresses) { AddressMap.clear(); QStringList AddressList = SplitStr(Addresses, ","); foreach(const QString & Address, AddressList) { StrPair BeginEnd = Split2(Address, "-"); QHostAddress Begin = QHostAddress(BeginEnd.first); QHostAddress End = BeginEnd.second.isEmpty() ? Begin : QHostAddress(BeginEnd.second); AddressMap.insert(End, Begin); } } EMatch MatchAddress(const QHostAddress& TestAddress) { if (AddressMap.isEmpty()) return eGlobal; if (TestAddress.isNull()) return eExact; auto I = AddressMap.lowerBound(TestAddress); if (I == AddressMap.end()) return eNone; if (I.key() < TestAddress) return eNone; if (TestAddress < I.value()) return eNone; return I.key() == I.value() ? eExact : eByRange; } EMatch MatchProtocol(COptionsWindow::ENetWfProt TestProt) { if (Protocol == COptionsWindow::eAny) return eGlobal; if (TestProt == COptionsWindow::eAny) return eExact; if (Protocol == TestProt) return eExact; return eNone; } struct SMatch { SMatch() { memset(this, 0, sizeof(SMatch)); } EMatch ByProg; EMatch ByPort; EMatch ByAddress; EMatch ByEndPoint; EMatch ByProtocol; COptionsWindow::ENetWfAction Action; }; bool MatchRule(const QString& TestProg, quint16 TestPort, const QHostAddress& TestAddress, COptionsWindow::ENetWfProt TestProt, SMatch* Match) { //SMatch Dummy; //if (!Match) Match = &Dummy; if (!(Match->ByProg = MatchProg(TestProg))) return false; if (!(Match->ByPort = MatchPort(TestPort))) return false; if (!(Match->ByAddress = MatchAddress(TestAddress))) return false; if (!(Match->ByProtocol = MatchProtocol(TestProt))) return false; if (Match->ByAddress > eGlobal && Match->ByPort > eGlobal) Match->ByEndPoint = Max(Match->ByAddress, Match->ByPort); Match->Action = Action; return true; } #define COMPARE_AND_RETURN(x, y) if(x != y) return x > y static bool IsBetterMatch(SMatch MyMatch, SMatch OtherMatch) { // 1. A rule for a specified program trumps a rule for all programs except a given one, trumps a rule for all programs COMPARE_AND_RETURN(MyMatch.ByProg, OtherMatch.ByProg); // 2. a rule with a Port or IP trumps a rule without // 2a. a rule with ip and port trums a rule with ip or port only // 2b. a rule with one ip trumps a rule with an ip range that is besides that on the same level COMPARE_AND_RETURN(MyMatch.ByEndPoint, OtherMatch.ByEndPoint); COMPARE_AND_RETURN(MyMatch.ByPort, OtherMatch.ByPort); COMPARE_AND_RETURN(MyMatch.ByAddress, OtherMatch.ByAddress); // 3. block rules trump allow rules if(MyMatch.Action == COptionsWindow::eBlock && OtherMatch.Action != COptionsWindow::eBlock) return true; // 4. a rule without a protocol means all protocols, a rule with a protocol trumps a rule without if its the only difference COMPARE_AND_RETURN(MyMatch.ByProtocol, OtherMatch.ByProtocol); return false; } QString Program; COptionsWindow::ENetWfAction Action; QMap PortMap; QMap AddressMap; COptionsWindow::ENetWfProt Protocol; }; void COptionsWindow::OnTestNetFwRule() { QString TestProg = ui.txtProgFwTest->text(); quint16 TestPort = ui.txtPortFwTest->text().toInt(); QHostAddress TestAddress = QHostAddress(ui.txtIPFwTest->text()); ENetWfProt TestProt = (ENetWfProt)ui.cmbProtFwTest->currentData().toInt(); QTreeWidgetItem* pBestItem = NULL; SFirewallRule BestRule; SFirewallRule::SMatch BestMatch; /*BestRule.SetPorts("100-200,400-500,700-800"); bool test1 = BestRule.MatchPort(500); bool test2 = BestRule.MatchPort(450); bool test3 = BestRule.MatchPort(350);*/ /*BestRule.SetAddresses("10.0.0.0-10.255.255.255,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255"); bool test1 = BestRule.MatchAddress(QHostAddress("10.70.0.1")); bool test2 = BestRule.MatchAddress(QHostAddress("8.8.8.8")); bool test3 = BestRule.MatchAddress(QHostAddress("244.123.0.0")); bool test4 = BestRule.MatchAddress(QHostAddress("192.168.100.1"));*/ for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeNetFw->topLevelItem(i); int Type = pItem->data(1, Qt::UserRole).toInt(); if (Type == -1) continue; // entry from template SFirewallRule Rule; Rule.Program = pItem->data(0, Qt::UserRole).toString(); Rule.Action = (ENetWfAction)pItem->data(1, Qt::UserRole).toInt(); Rule.SetPorts(pItem->data(2, Qt::UserRole).toString()); Rule.SetAddresses(pItem->data(3, Qt::UserRole).toString()); Rule.Protocol = (ENetWfProt)pItem->data(4, Qt::UserRole).toInt(); SFirewallRule::SMatch Match; if (Rule.MatchRule(TestProg, TestPort, TestAddress, TestProt, &Match)) { if (!pBestItem || SFirewallRule::IsBetterMatch(Match, BestMatch)) { BestRule = Rule; BestMatch = Match; pBestItem = pItem; } else if(!SFirewallRule::IsBetterMatch(BestMatch, Match)) // if this is not true we have a conflict { COptionsWindow__SetRowColor(pItem, true, true); COptionsWindow__SetRowColor(pBestItem, true, true); pBestItem = NULL; continue; } COptionsWindow__SetRowColor(pItem, true, false, Rule.Action == eBlock, false); } else COptionsWindow__SetRowColor(pItem, false); } if(pBestItem) COptionsWindow__SetRowColor(pBestItem, true, false, BestRule.Action == eBlock, true); // // rule merging // if the rule is for the same prog and has the same action // merge all rules with ip only together // merge all rules with ports only together // // } void COptionsWindow::OnClearNetFwTest() { ui.txtProgFwTest->setText(""); ui.txtPortFwTest->setText(""); ui.txtIPFwTest->setText(""); ui.cmbProtFwTest->setCurrentIndex(0); for (int i = 0; i < ui.treeNetFw->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeNetFw->topLevelItem(i); COptionsWindow__SetRowColor(pItem, false); } }