File indexing completed on 2024-12-08 08:02:32
0001 /* 0002 SPDX-FileCopyrightText: 2019 Bruce Anderson <banderson19com@san.rr.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "wireguardinterfacewidget.h" 0007 #include "simpleiplistvalidator.h" 0008 #include "wireguardkeyvalidator.h" 0009 #include "wireguardtabwidget.h" 0010 0011 #include <QFile> 0012 #include <QFileInfo> 0013 #include <QPointer> 0014 #include <QStandardItemModel> 0015 0016 #include <KColorScheme> 0017 #include <KConfig> 0018 #include <KConfigGroup> 0019 #include <NetworkManagerQt/Ipv4Setting> 0020 #include <NetworkManagerQt/Ipv6Setting> 0021 #include <NetworkManagerQt/Utils> 0022 0023 // Tags used in a WireGuard .conf file - Used for importing 0024 #define PNM_WG_CONF_TAG_INTERFACE "[Interface]" 0025 #define PNM_WG_CONF_TAG_ADDRESS "Address" 0026 #define PNM_WG_CONF_TAG_LISTEN_PORT "ListenPort" 0027 #define PNM_WG_CONF_TAG_MTU "MTU" 0028 #define PNM_WG_CONF_TAG_DNS "DNS" 0029 #define PNM_WG_CONF_TAG_FWMARK "FwMark" 0030 #define PNM_WG_CONF_TAG_PRIVATE_KEY "PrivateKey" 0031 #define PNM_WG_CONF_TAG_PEER "[Peer]" 0032 #define PNM_WG_CONF_TAG_PUBLIC_KEY "PublicKey" 0033 #define PNM_WG_CONF_TAG_PRESHARED_KEY "PresharedKey" 0034 #define PNM_WG_CONF_TAG_ALLOWED_IPS "AllowedIPs" 0035 #define PNM_WG_CONF_TAG_ENDPOINT "Endpoint" 0036 #define PNM_WG_CONF_TAG_PERSISTENT_KEEPALIVE "PersistentKeepalive" 0037 #define PNM_WG_CONF_TAG_TABLE "Table" 0038 #define PNM_WG_CONF_TAG_PRE_UP "PreUp" 0039 #define PNM_WG_CONF_TAG_POST_UP "PostUp" 0040 #define PNM_WG_CONF_TAG_PRE_DOWN "PreDown" 0041 #define PNM_WG_CONF_TAG_POST_DOWN "PostDown" 0042 0043 #define PNM_WG_KEY_PEERS "peers" 0044 #define PNM_WG_KEY_MTU "mtu" 0045 #define PNM_WG_KEY_PEER_ROUTES "peer-routes" 0046 #define PNM_WG_PEER_KEY_ALLOWED_IPS "allowed-ips" 0047 #define PNM_WG_PEER_KEY_ENDPOINT "endpoint" 0048 #define PNM_WG_PEER_KEY_PERSISTENT_KEEPALIVE "persistent-keepalive" 0049 #define PNM_WG_PEER_KEY_PRESHARED_KEY "preshared-key" 0050 #define PNM_WG_PEER_KEY_PRESHARED_KEY_FLAGS "preshared-key-flags" 0051 #define PNM_WG_PEER_KEY_PUBLIC_KEY "public-key" 0052 0053 // Keys for the NetworkManager configuration 0054 #define PNM_SETTING_WIREGUARD_SETTING_NAME "wireguard" 0055 0056 #define PNM_WG_KEY_FWMARK "fwmark" 0057 #define PNM_WG_KEY_LISTEN_PORT "listen-port" 0058 #define PNM_WG_KEY_PRIVATE_KEY "private-key" 0059 #define PNM_WG_KEY_PRIVATE_KEY_FLAGS "private-key-flags" 0060 0061 class WireGuardInterfaceWidget::Private 0062 { 0063 public: 0064 ~Private(); 0065 0066 Ui_WireGuardInterfaceProp ui; 0067 NetworkManager::WireGuardSetting::Ptr setting; 0068 KSharedConfigPtr config; 0069 QPalette warningPalette; 0070 QPalette normalPalette; 0071 WireGuardKeyValidator *keyValidator; 0072 QRegularExpressionValidator *fwmarkValidator; 0073 QIntValidator *mtuValidator; 0074 QIntValidator *portValidator; 0075 bool privateKeyValid = false; 0076 bool fwmarkValid = true; 0077 bool listenPortValid = true; 0078 bool peersValid = false; 0079 NMVariantMapList peers; 0080 }; 0081 0082 WireGuardInterfaceWidget::Private::~Private() 0083 { 0084 delete keyValidator; 0085 delete fwmarkValidator; 0086 delete mtuValidator; 0087 delete portValidator; 0088 } 0089 0090 WireGuardInterfaceWidget::WireGuardInterfaceWidget(const NetworkManager::Setting::Ptr &setting, QWidget *parent, Qt::WindowFlags f) 0091 : SettingWidget(setting, parent, f) 0092 , d(new Private) 0093 { 0094 d->ui.setupUi(this); 0095 d->setting = setting.staticCast<NetworkManager::WireGuardSetting>(); 0096 d->config = KSharedConfig::openConfig(); 0097 d->warningPalette = KColorScheme::createApplicationPalette(d->config); 0098 d->normalPalette = KColorScheme::createApplicationPalette(d->config); 0099 KColorScheme::adjustBackground(d->warningPalette, KColorScheme::NegativeBackground, QPalette::Base, KColorScheme::ColorSet::View, d->config); 0100 0101 KColorScheme::adjustBackground(d->normalPalette, KColorScheme::NormalBackground, QPalette::Base, KColorScheme::ColorSet::View, d->config); 0102 0103 connect(d->ui.privateKeyLineEdit, &PasswordField::textChanged, this, &WireGuardInterfaceWidget::checkPrivateKeyValid); 0104 connect(d->ui.privateKeyLineEdit, &PasswordField::passwordOptionChanged, this, &WireGuardInterfaceWidget::checkPrivateKeyValid); 0105 connect(d->ui.fwmarkLineEdit, &QLineEdit::textChanged, this, &WireGuardInterfaceWidget::checkFwmarkValid); 0106 connect(d->ui.listenPortLineEdit, &QLineEdit::textChanged, this, &WireGuardInterfaceWidget::checkListenPortValid); 0107 connect(d->ui.btnPeers, &QPushButton::clicked, this, &WireGuardInterfaceWidget::showPeers); 0108 0109 d->ui.privateKeyLineEdit->setPasswordModeEnabled(true); 0110 d->ui.privateKeyLineEdit->setPasswordOptionsEnabled(true); 0111 d->ui.privateKeyLineEdit->setPasswordNotSavedEnabled(false); 0112 0113 // This is done as a private variable rather than a local variable so it can be 0114 // used both here and to validate the private key later 0115 d->keyValidator = new WireGuardKeyValidator(this); 0116 0117 // Create validator for listen port 0118 d->portValidator = new QIntValidator; 0119 d->portValidator->setBottom(0); 0120 d->portValidator->setTop(65535); 0121 0122 // Create a validator for the fwmark input. Acceptable 0123 // inputs are: "off" and numbers in either decimal 0124 // or hex (with 0x prefix) 0125 d->fwmarkValidator = new QRegularExpressionValidator(QRegularExpression("(off)|([0-9]{0,10})|(0x[0-9a-fA-F]{1,8})")); 0126 d->ui.fwmarkLineEdit->setValidator(d->fwmarkValidator); 0127 0128 // Create a validator for the MTU field. 0129 d->mtuValidator = new QIntValidator(); 0130 d->mtuValidator->setBottom(0); 0131 d->ui.mtuLineEdit->setValidator(d->mtuValidator); 0132 0133 // Default Peer Routes to true 0134 d->ui.peerRouteCheckBox->setChecked(true); 0135 0136 // Connect for setting check 0137 watchChangedSetting(); 0138 0139 KAcceleratorManager::manage(this); 0140 0141 if (setting && !setting->isNull()) { 0142 loadConfig(d->setting); 0143 } 0144 0145 // Set the initial backgrounds on all the widgets 0146 checkPrivateKeyValid(); 0147 } 0148 0149 WireGuardInterfaceWidget::~WireGuardInterfaceWidget() 0150 { 0151 delete d; 0152 } 0153 0154 void WireGuardInterfaceWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) 0155 { 0156 NetworkManager::WireGuardSetting::Ptr wireGuardSetting = setting.staticCast<NetworkManager::WireGuardSetting>(); 0157 d->ui.privateKeyLineEdit->setText(wireGuardSetting->privateKey()); 0158 0159 if (wireGuardSetting->listenPort() != 0) 0160 d->ui.listenPortLineEdit->setText(QString::number(wireGuardSetting->listenPort())); 0161 else 0162 d->ui.listenPortLineEdit->clear(); 0163 0164 if (wireGuardSetting->fwmark() != 0) 0165 d->ui.fwmarkLineEdit->setText(QString::number(wireGuardSetting->fwmark())); 0166 else 0167 d->ui.fwmarkLineEdit->clear(); 0168 0169 if (wireGuardSetting->mtu() != 0) 0170 d->ui.mtuLineEdit->setText(QString::number(wireGuardSetting->mtu())); 0171 else 0172 d->ui.mtuLineEdit->clear(); 0173 0174 d->ui.peerRouteCheckBox->setChecked(wireGuardSetting->peerRoutes()); 0175 0176 NetworkManager::Setting::SecretFlags type = wireGuardSetting->privateKeyFlags(); 0177 switch (type) { 0178 case NetworkManager::Setting::AgentOwned: 0179 d->ui.privateKeyLineEdit->setPasswordOption(PasswordField::StoreForUser); 0180 break; 0181 case NetworkManager::Setting::None: 0182 d->ui.privateKeyLineEdit->setPasswordOption(PasswordField::StoreForAllUsers); 0183 break; 0184 // Not saved is not a valid option for the private key so set it to StoreForUser instead 0185 case NetworkManager::Setting::NotSaved: 0186 d->ui.privateKeyLineEdit->setPasswordOption(PasswordField::StoreForUser); 0187 break; 0188 case NetworkManager::Setting::NotRequired: 0189 d->ui.privateKeyLineEdit->setPasswordOption(PasswordField::NotRequired); 0190 break; 0191 } 0192 0193 d->peers = wireGuardSetting->peers(); 0194 loadSecrets(setting); 0195 } 0196 0197 void WireGuardInterfaceWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) 0198 { 0199 NetworkManager::WireGuardSetting::Ptr wireGuardSetting = setting.staticCast<NetworkManager::WireGuardSetting>(); 0200 if (wireGuardSetting) { 0201 const QString key = wireGuardSetting->privateKey(); 0202 if (!key.isEmpty()) 0203 d->ui.privateKeyLineEdit->setText(key); 0204 0205 const NMVariantMapList peers = wireGuardSetting->peers(); 0206 if (!peers.isEmpty()) { 0207 // For each of the peers returned, see if it contains a preshared key 0208 for (QList<QVariantMap>::const_iterator i = peers.cbegin(); i != peers.cend(); i++) { 0209 if (i->contains(PNM_WG_PEER_KEY_PRESHARED_KEY)) { 0210 // We have a preshared key so find the matching public key in the local peer list 0211 QString currentPublicKey = (*i)[PNM_WG_PEER_KEY_PUBLIC_KEY].toString(); 0212 if (!currentPublicKey.isEmpty()) { 0213 for (QList<QVariantMap>::iterator j = d->peers.begin(); j != d->peers.end(); j++) { 0214 if ((*j)[PNM_WG_PEER_KEY_PUBLIC_KEY].toString() == currentPublicKey) { 0215 (*j)[PNM_WG_PEER_KEY_PRESHARED_KEY] = (*i)[PNM_WG_PEER_KEY_PRESHARED_KEY].toString(); 0216 break; 0217 } 0218 } 0219 } 0220 } 0221 } 0222 } 0223 } 0224 // On the assumption that a saved configuration is valid (because how could it be saved if it 0225 // wasn't valid) then the peers section is valid unless it didn't get a preshared key if one 0226 // is required, so a simple minded "validity" check is done here. Real validity checks are done 0227 // when the peers widget is open which is the only time changes which might be invalid are 0228 // possible. 0229 d->peersValid = true; 0230 for (QList<QVariantMap>::iterator j = d->peers.begin(); j != d->peers.end(); j++) { 0231 if ((*j).contains(PNM_WG_PEER_KEY_PRESHARED_KEY_FLAGS) && (*j)[PNM_WG_PEER_KEY_PRESHARED_KEY_FLAGS] != NetworkManager::Setting::NotRequired 0232 && (!(*j).contains(PNM_WG_PEER_KEY_PRESHARED_KEY) || (*j)[PNM_WG_PEER_KEY_PRESHARED_KEY].toString().isEmpty())) { 0233 d->peersValid = false; 0234 break; 0235 } 0236 } 0237 } 0238 0239 QVariantMap WireGuardInterfaceWidget::setting() const 0240 { 0241 NetworkManager::WireGuardSetting wgSetting; 0242 QString val = d->ui.fwmarkLineEdit->displayText(); 0243 0244 if (!val.isEmpty()) 0245 wgSetting.setFwmark(val.toUInt()); 0246 0247 val = d->ui.listenPortLineEdit->displayText(); 0248 if (!val.isEmpty()) 0249 wgSetting.setListenPort(val.toUInt()); 0250 0251 val = d->ui.mtuLineEdit->displayText(); 0252 if (!val.isEmpty()) 0253 wgSetting.setMtu(val.toUInt()); 0254 0255 val = d->ui.privateKeyLineEdit->text(); 0256 if (!val.isEmpty()) 0257 wgSetting.setPrivateKey(val); 0258 0259 wgSetting.setPeerRoutes(d->ui.peerRouteCheckBox->isChecked()); 0260 0261 PasswordField::PasswordOption option = d->ui.privateKeyLineEdit->passwordOption(); 0262 switch (option) { 0263 case PasswordField::StoreForUser: 0264 wgSetting.setPrivateKeyFlags(NetworkManager::Setting::AgentOwned); 0265 break; 0266 case PasswordField::StoreForAllUsers: 0267 wgSetting.setPrivateKeyFlags(NetworkManager::Setting::None); 0268 break; 0269 // Always Ask is not a valid option for the private key so set it to AgentOwned instead 0270 case PasswordField::AlwaysAsk: 0271 wgSetting.setPrivateKeyFlags(NetworkManager::Setting::AgentOwned); 0272 break; 0273 case PasswordField::NotRequired: 0274 wgSetting.setPrivateKeyFlags(NetworkManager::Setting::NotRequired); 0275 break; 0276 } 0277 wgSetting.setPeers(d->peers); 0278 return wgSetting.toMap(); 0279 } 0280 0281 bool WireGuardInterfaceWidget::isValid() const 0282 { 0283 return d->privateKeyValid && d->fwmarkValid && d->listenPortValid && d->peersValid; 0284 } 0285 0286 void WireGuardInterfaceWidget::checkPrivateKeyValid() 0287 { 0288 int pos = 0; 0289 PasswordField *widget = d->ui.privateKeyLineEdit; 0290 QString value = widget->text(); 0291 bool valid = (QValidator::Acceptable == d->keyValidator->validate(value, pos)); 0292 d->privateKeyValid = valid; 0293 setBackground(widget, valid); 0294 slotWidgetChanged(); 0295 } 0296 void WireGuardInterfaceWidget::checkFwmarkValid() 0297 { 0298 int pos = 0; 0299 QLineEdit *widget = d->ui.fwmarkLineEdit; 0300 QString value = widget->displayText(); 0301 d->fwmarkValid = QValidator::Acceptable == widget->validator()->validate(value, pos) || value.isEmpty(); 0302 setBackground(widget, d->fwmarkValid); 0303 slotWidgetChanged(); 0304 } 0305 0306 void WireGuardInterfaceWidget::checkListenPortValid() 0307 { 0308 int pos = 0; 0309 QLineEdit *widget = d->ui.listenPortLineEdit; 0310 QString value = widget->displayText(); 0311 d->listenPortValid = QValidator::Acceptable == d->portValidator->validate(value, pos) || value.isEmpty(); 0312 setBackground(widget, d->listenPortValid); 0313 slotWidgetChanged(); 0314 } 0315 0316 void WireGuardInterfaceWidget::setBackground(QWidget *w, bool result) const 0317 { 0318 if (result) 0319 w->setPalette(d->normalPalette); 0320 else 0321 w->setPalette(d->warningPalette); 0322 } 0323 0324 QString WireGuardInterfaceWidget::supportedFileExtensions() 0325 { 0326 return "*.conf"; 0327 } 0328 0329 void WireGuardInterfaceWidget::showPeers() 0330 { 0331 QPointer<WireGuardTabWidget> peers = new WireGuardTabWidget(d->peers, this); 0332 peers->setAttribute(Qt::WA_DeleteOnClose); 0333 0334 connect(peers.data(), &WireGuardTabWidget::accepted, [peers, this]() { 0335 NMVariantMapList peersData = peers->setting(); 0336 if (!peersData.isEmpty()) { 0337 d->peers = peersData; 0338 // The peers widget won't allow "OK" to be hit 0339 // unless all the peers are valid so no need to check 0340 d->peersValid = true; 0341 slotWidgetChanged(); 0342 } 0343 }); 0344 peers->setModal(true); 0345 peers->show(); 0346 } 0347 0348 NMVariantMapMap WireGuardInterfaceWidget::importConnectionSettings(const QString &fileName) 0349 { 0350 NMVariantMapMap result; 0351 0352 QFile impFile(fileName); 0353 QList<NetworkManager::IpAddress> ipv4AddressList; 0354 QList<NetworkManager::IpAddress> ipv6AddressList; 0355 0356 if (!impFile.open(QFile::ReadOnly | QFile::Text)) { 0357 return result; 0358 } 0359 0360 const QString connectionName = QFileInfo(fileName).completeBaseName(); 0361 NMVariantMapList peers; 0362 QVariantMap *currentPeer = nullptr; 0363 WireGuardKeyValidator keyValidator; 0364 NetworkManager::Ipv4Setting ipv4Setting; 0365 NetworkManager::Ipv6Setting ipv6Setting; 0366 NetworkManager::WireGuardSetting wgSetting; 0367 0368 bool havePrivateKey = false; 0369 bool haveIpv4Setting = false; 0370 bool haveIpv6Setting = false; 0371 // Set the "PEER" elements true because they 0372 // need to be true to allocate the 0373 // first [Peer] section below 0374 bool havePublicKey = true; 0375 bool haveAllowedIps = true; 0376 int pos = 0; 0377 0378 QTextStream in(&impFile); 0379 enum { IDLE, INTERFACE_SECTION, PEER_SECTION } currentState = IDLE; 0380 0381 ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Disabled); 0382 ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Ignored); 0383 0384 while (!in.atEnd()) { 0385 QStringList keyValue; 0386 QString line = in.readLine(); 0387 0388 // Remove comments starting with '#' 0389 if (int index = line.indexOf(QLatin1Char('#')) > 0) 0390 line.truncate(index); 0391 0392 // Ignore blank lines 0393 if (line.isEmpty()) 0394 continue; 0395 0396 keyValue.clear(); 0397 keyValue << line.split(QLatin1Char('=')); 0398 0399 if (keyValue[0] == PNM_WG_CONF_TAG_INTERFACE) { 0400 currentState = INTERFACE_SECTION; 0401 continue; 0402 } else if (keyValue[0] == PNM_WG_CONF_TAG_PEER) { 0403 // Check to make sure the previous PEER section has 0404 // all the required elements. If not it's an error 0405 // so just return the empty result. 0406 if (!havePublicKey || !haveAllowedIps) { 0407 return result; 0408 } else { 0409 havePublicKey = false; 0410 haveAllowedIps = false; 0411 currentState = PEER_SECTION; 0412 peers.append(*(new QVariantMap)); 0413 currentPeer = &peers[peers.size() - 1]; 0414 continue; 0415 } 0416 } 0417 0418 // If we didn't get an '=' sign in the line, it's probably an error but 0419 // we're going to treat it as a comment and ignore it 0420 if (keyValue.length() < 2) 0421 continue; 0422 0423 QString key = keyValue[0].trimmed(); 0424 0425 // If we are in the [Interface] section look for the possible tags 0426 if (currentState == INTERFACE_SECTION) { 0427 // Address 0428 if (key == PNM_WG_CONF_TAG_ADDRESS) { 0429 QStringList valueList = keyValue[1].split(QLatin1Char(',')); 0430 if (valueList.isEmpty()) 0431 return result; 0432 0433 for (const QString &address : valueList) { 0434 const QPair<QHostAddress, int> addressIn = QHostAddress::parseSubnet(address.trimmed()); 0435 auto addr = new NetworkManager::IpAddress; 0436 addr->setIp(addressIn.first); 0437 addr->setPrefixLength(addressIn.second); 0438 if (addressIn.first.protocol() == QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) { 0439 ipv4AddressList.append(*addr); 0440 } else if (addressIn.first.protocol() == QAbstractSocket::NetworkLayerProtocol::IPv6Protocol) { 0441 ipv6AddressList.append(*addr); 0442 } else { // Error condition 0443 return result; 0444 } 0445 } 0446 if (!ipv4AddressList.isEmpty()) { 0447 ipv4Setting.setAddresses(ipv4AddressList); 0448 ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Manual); 0449 haveIpv4Setting = true; 0450 } 0451 if (!ipv6AddressList.isEmpty()) { 0452 ipv6Setting.setAddresses(ipv6AddressList); 0453 ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Manual); 0454 haveIpv6Setting = true; 0455 } 0456 } 0457 0458 // Listen Port 0459 else if (key == PNM_WG_CONF_TAG_LISTEN_PORT) { 0460 uint val = keyValue[1].toUInt(); 0461 if (val <= 65535) 0462 wgSetting.setListenPort(val); 0463 } else if (key == PNM_WG_CONF_TAG_PRIVATE_KEY) { 0464 QString val = keyValue[1].trimmed(); 0465 // WireGuard keys present a slight problem because they 0466 // must end in '=' which is removed during the 'split' above 0467 // so if there are 3 parts and the 3 is empty, there must 0468 // have been an '=' so add it back on 0469 if (keyValue.size() == 3 && keyValue[2].isEmpty()) 0470 val += "="; 0471 if (QValidator::Acceptable == keyValidator.validate(val, pos)) { 0472 wgSetting.setPrivateKey(val); 0473 havePrivateKey = true; 0474 } 0475 } else if (key == PNM_WG_CONF_TAG_DNS) { 0476 QStringList addressList = keyValue[1].split(QLatin1Char(',')); 0477 QList<QHostAddress> ipv4DnsList; 0478 QList<QHostAddress> ipv6DnsList; 0479 if (!addressList.isEmpty()) { 0480 for (const QString &address : addressList) { 0481 const QPair<QHostAddress, int> addressIn = QHostAddress::parseSubnet(address.trimmed()); 0482 if (addressIn.first.protocol() == QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) { 0483 ipv4DnsList.append(addressIn.first); 0484 } else if (addressIn.first.protocol() == QAbstractSocket::NetworkLayerProtocol::IPv6Protocol) { 0485 ipv6DnsList.append(addressIn.first); 0486 } else { // Error condition 0487 return result; 0488 } 0489 } 0490 } 0491 0492 // If there are any addresses put them on the correct tab and set the "method" to 0493 // "Automatic (Only addresses)" by setting "ignore-auto-dns=true" 0494 if (!ipv4DnsList.isEmpty()) { 0495 if (ipv4Setting.method() == NetworkManager::Ipv4Setting::Disabled) 0496 ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Automatic); 0497 ipv4Setting.setIgnoreAutoDns(true); 0498 ipv4Setting.setDns(ipv4DnsList); 0499 haveIpv4Setting = true; 0500 } 0501 0502 if (!ipv6DnsList.isEmpty()) { 0503 ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Automatic); 0504 ipv6Setting.setIgnoreAutoDns(true); 0505 ipv6Setting.setDns(ipv6DnsList); 0506 haveIpv6Setting = true; 0507 } 0508 } else if (key == PNM_WG_CONF_TAG_MTU) { 0509 uint val = keyValue[1].toUInt(); 0510 if (val > 0) 0511 wgSetting.setMtu(val); 0512 } else if (key == PNM_WG_CONF_TAG_FWMARK) { 0513 uint val; 0514 if (keyValue[1].trimmed().toLower() == QLatin1String("off")) 0515 val = 0; 0516 else 0517 val = keyValue[1].toUInt(); 0518 wgSetting.setFwmark(val); 0519 } else if (key == PNM_WG_CONF_TAG_TABLE // 0520 || key == PNM_WG_CONF_TAG_PRE_UP // 0521 || key == PNM_WG_CONF_TAG_POST_UP // 0522 || key == PNM_WG_CONF_TAG_PRE_DOWN // 0523 || key == PNM_WG_CONF_TAG_POST_DOWN) { 0524 // plasma-nm does not handle these items 0525 } else { 0526 // We got a wrong field in the Interface section so it 0527 // is an error 0528 break; 0529 } 0530 } else if (currentState == PEER_SECTION) { 0531 // Public Key 0532 if (key == PNM_WG_CONF_TAG_PUBLIC_KEY) { 0533 QString val = keyValue[1].trimmed(); 0534 // WireGuard keys present a slight problem because they 0535 // must end in '=' which is removed during the 'split' above 0536 // so if there are 3 parts and the 3 is empty, there must 0537 // have been an '=' so add it back on 0538 if (keyValue.size() == 3 && keyValue[2].isEmpty()) 0539 val += "="; 0540 0541 if (QValidator::Acceptable == keyValidator.validate(val, pos)) { 0542 currentPeer->insert(PNM_WG_PEER_KEY_PUBLIC_KEY, val); 0543 havePublicKey = true; 0544 } 0545 } else if (key == PNM_WG_CONF_TAG_ALLOWED_IPS) { 0546 SimpleIpListValidator validator(SimpleIpListValidator::WithCidr, SimpleIpListValidator::Both); 0547 QString val = keyValue[1].trimmed(); 0548 if (QValidator::Acceptable == validator.validate(val, pos)) { 0549 QStringList valList = val.split(QLatin1Char(',')); 0550 for (QString &str : valList) 0551 str = str.trimmed(); 0552 currentPeer->insert(PNM_WG_PEER_KEY_ALLOWED_IPS, valList); 0553 haveAllowedIps = true; 0554 } 0555 } else if (key == PNM_WG_CONF_TAG_ENDPOINT) { 0556 if (keyValue[1].length() > 0) 0557 currentPeer->insert(PNM_WG_PEER_KEY_ENDPOINT, keyValue[1].trimmed()); 0558 } else if (key == PNM_WG_CONF_TAG_PRESHARED_KEY) { 0559 QString val = keyValue[1].trimmed(); 0560 // WireGuard keys present a slight problem because they 0561 // must end in '=' which is removed during the 'split' above 0562 // so if there are 3 parts and the 3 is empty, there must 0563 // have been an '=' so add it back on 0564 if (keyValue.size() == 3 && keyValue[2].isEmpty()) 0565 val += "="; 0566 0567 if (QValidator::Acceptable == keyValidator.validate(val, pos)) { 0568 currentPeer->insert(PNM_WG_PEER_KEY_PRESHARED_KEY, val); 0569 } 0570 } 0571 } else { 0572 return result; 0573 } 0574 } 0575 if (!havePrivateKey || !haveAllowedIps || !havePublicKey) 0576 return result; 0577 0578 QVariantMap conn; 0579 wgSetting.setPeers(peers); 0580 conn.insert("id", connectionName); 0581 conn.insert("interface-name", connectionName); 0582 conn.insert("type", "wireguard"); 0583 conn.insert("autoconnect", "false"); 0584 result.insert("connection", conn); 0585 result.insert("wireguard", wgSetting.toMap()); 0586 if (haveIpv4Setting) 0587 result.insert("ipv4", ipv4Setting.toMap()); 0588 if (haveIpv6Setting) 0589 result.insert("ipv6", ipv6Setting.toMap()); 0590 0591 impFile.close(); 0592 return result; 0593 } 0594 0595 #include "moc_wireguardinterfacewidget.cpp"