File indexing completed on 2024-04-21 04:00:08
0001 /* 0002 SPDX-FileCopyrightText: 2019 Jan Grulich <jgrulich@redhat.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "wireguardsetting.h" 0008 #include "wireguardsetting_p.h" 0009 0010 #include <QDebug> 0011 0012 #if !NM_CHECK_VERSION(1, 16, 0) 0013 #define NM_SETTING_WIREGUARD_SETTING_NAME "wireguard" 0014 0015 #define NM_SETTING_WIREGUARD_FWMARK "fwmark" 0016 #define NM_SETTING_WIREGUARD_LISTEN_PORT "listen-port" 0017 #define NM_SETTING_WIREGUARD_PRIVATE_KEY "private-key" 0018 #define NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS "private-key-flags" 0019 #define NM_SETTING_WIREGUARD_PEERS "peers" 0020 #define NM_SETTING_WIREGUARD_MTU "mtu" 0021 #define NM_SETTING_WIREGUARD_PEER_ROUTES "peer-routes" 0022 0023 #define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY "preshared-key" 0024 #define NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS "preshared-key-flags" 0025 #define NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY "public-key" 0026 #endif 0027 0028 NetworkManager::WireGuardSettingPrivate::WireGuardSettingPrivate() 0029 : name(NM_SETTING_WIREGUARD_SETTING_NAME) 0030 , fwmark(0) 0031 , listenPort(0) 0032 , mtu(0) 0033 , peerRoutes(true) 0034 , privateKeyFlags(NetworkManager::Setting::None) 0035 { 0036 } 0037 0038 NetworkManager::WireGuardSetting::WireGuardSetting() 0039 : Setting(Setting::WireGuard) 0040 , d_ptr(new WireGuardSettingPrivate()) 0041 { 0042 } 0043 0044 NetworkManager::WireGuardSetting::WireGuardSetting(const Ptr &other) 0045 : Setting(other) 0046 , d_ptr(new WireGuardSettingPrivate()) 0047 { 0048 setFwmark(other->fwmark()); 0049 setListenPort(other->listenPort()); 0050 setMtu(other->mtu()); 0051 setPeerRoutes(other->peerRoutes()); 0052 setPeers(other->peers()); 0053 setPrivateKey(other->privateKey()); 0054 setPrivateKeyFlags(other->privateKeyFlags()); 0055 } 0056 0057 NetworkManager::WireGuardSetting::~WireGuardSetting() 0058 { 0059 delete d_ptr; 0060 } 0061 0062 QString NetworkManager::WireGuardSetting::name() const 0063 { 0064 Q_D(const WireGuardSetting); 0065 0066 return d->name; 0067 } 0068 0069 quint32 NetworkManager::WireGuardSetting::fwmark() const 0070 { 0071 Q_D(const WireGuardSetting); 0072 0073 return d->fwmark; 0074 } 0075 0076 void NetworkManager::WireGuardSetting::setFwmark(quint32 fwmark) 0077 { 0078 Q_D(WireGuardSetting); 0079 0080 d->fwmark = fwmark; 0081 } 0082 0083 quint32 NetworkManager::WireGuardSetting::listenPort() const 0084 { 0085 Q_D(const WireGuardSetting); 0086 0087 return d->listenPort; 0088 } 0089 0090 void NetworkManager::WireGuardSetting::setListenPort(quint32 port) 0091 { 0092 Q_D(WireGuardSetting); 0093 0094 d->listenPort = port; 0095 } 0096 0097 quint32 NetworkManager::WireGuardSetting::mtu() const 0098 { 0099 Q_D(const WireGuardSetting); 0100 0101 return d->mtu; 0102 } 0103 0104 void NetworkManager::WireGuardSetting::setMtu(quint32 mtu) 0105 { 0106 Q_D(WireGuardSetting); 0107 0108 d->mtu = mtu; 0109 } 0110 0111 bool NetworkManager::WireGuardSetting::peerRoutes() const 0112 { 0113 Q_D(const WireGuardSetting); 0114 0115 return d->peerRoutes; 0116 } 0117 0118 void NetworkManager::WireGuardSetting::setPeerRoutes(bool peerRoutes) 0119 { 0120 Q_D(WireGuardSetting); 0121 0122 d->peerRoutes = peerRoutes; 0123 } 0124 0125 NMVariantMapList NetworkManager::WireGuardSetting::peers() const 0126 { 0127 Q_D(const WireGuardSetting); 0128 0129 return d->peers; 0130 } 0131 0132 void NetworkManager::WireGuardSetting::setPeers(const NMVariantMapList &peers) 0133 { 0134 Q_D(WireGuardSetting); 0135 0136 d->peers = peers; 0137 } 0138 0139 QString NetworkManager::WireGuardSetting::privateKey() const 0140 { 0141 Q_D(const WireGuardSetting); 0142 0143 return d->privateKey; 0144 } 0145 0146 void NetworkManager::WireGuardSetting::setPrivateKey(const QString &key) 0147 { 0148 Q_D(WireGuardSetting); 0149 0150 d->privateKey = key; 0151 } 0152 0153 NetworkManager::Setting::SecretFlags NetworkManager::WireGuardSetting::privateKeyFlags() const 0154 { 0155 Q_D(const WireGuardSetting); 0156 0157 return d->privateKeyFlags; 0158 } 0159 0160 void NetworkManager::WireGuardSetting::setPrivateKeyFlags(NetworkManager::Setting::SecretFlags flags) 0161 { 0162 Q_D(WireGuardSetting); 0163 0164 d->privateKeyFlags = flags; 0165 } 0166 0167 void NetworkManager::WireGuardSetting::secretsFromMap(const QVariantMap &secrets) 0168 { 0169 if (secrets.contains(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY))) { 0170 setPrivateKey(secrets.value(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY)).toString()); 0171 } 0172 0173 if (secrets.contains(QLatin1String(NM_SETTING_WIREGUARD_PEERS))) { 0174 NMVariantMapList listOfPeers = qdbus_cast<NMVariantMapList>(secrets.value(QLatin1String(NM_SETTING_WIREGUARD_PEERS))); 0175 NMVariantMapList origPeers = peers(); 0176 0177 for (const QVariantMap &peer : listOfPeers) { 0178 if (peer.contains(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY))) { 0179 QString presharedKey = peer.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)).toString(); 0180 QString publicKey = peer.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)).toString(); 0181 for (int i = 0; i < origPeers.size(); i++) { 0182 if (origPeers[i][QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)].toString() == publicKey) { 0183 origPeers[i].insert(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY), presharedKey); 0184 } 0185 } 0186 } 0187 } 0188 setPeers(origPeers); 0189 } 0190 } 0191 0192 QVariantMap NetworkManager::WireGuardSetting::secretsToMap() const 0193 { 0194 QVariantMap secrets; 0195 0196 if (!privateKey().isEmpty()) { 0197 secrets.insert(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY), privateKey()); 0198 } 0199 0200 NMVariantMapList peersSecrets; 0201 0202 for (const QVariantMap &map : peers()) { 0203 if (map.contains(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)) && map.contains(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY))) { 0204 QVariantMap newMap; 0205 newMap.insert(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY), map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY))); 0206 newMap.insert(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY), map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY))); 0207 0208 peersSecrets << newMap; 0209 } 0210 } 0211 0212 if (!peersSecrets.isEmpty()) { 0213 secrets.insert(QLatin1String(NM_SETTING_WIREGUARD_PEERS), QVariant::fromValue(peersSecrets)); 0214 } 0215 0216 return secrets; 0217 } 0218 0219 void NetworkManager::WireGuardSetting::secretsFromStringMap(const NMStringMap &map) 0220 { 0221 QVariantMap secretsMap; 0222 NMVariantMapList peers; 0223 0224 auto it = map.constBegin(); 0225 while (it != map.constEnd()) { 0226 if (it.key() == QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY)) { 0227 secretsMap.insert(it.key(), it.value()); 0228 } 0229 0230 if (it.key().startsWith(QLatin1String(NM_SETTING_WIREGUARD_PEERS)) && it.key().endsWith(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY))) { 0231 QStringList peerStrList = it.key().split(QLatin1Char('.')); 0232 0233 QVariantMap peer; 0234 peer.insert(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY), peerStrList.at(1)); 0235 peer.insert(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY), it.value()); 0236 0237 peers << peer; 0238 } 0239 ++it; 0240 } 0241 0242 if (!peers.isEmpty()) { 0243 secretsMap.insert(QLatin1String(NM_SETTING_WIREGUARD_PEERS), QVariant::fromValue(peers)); 0244 } 0245 0246 secretsFromMap(secretsMap); 0247 } 0248 0249 NMStringMap NetworkManager::WireGuardSetting::secretsToStringMap() const 0250 { 0251 NMStringMap ret; 0252 QVariantMap secretsMap = secretsToMap(); 0253 0254 auto it = secretsMap.constBegin(); 0255 while (it != secretsMap.constEnd()) { 0256 if (it.key() == QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY)) { 0257 ret.insert(it.key(), it.value().toString()); 0258 } 0259 0260 if (it.key() == QLatin1String(NM_SETTING_WIREGUARD_PEERS)) { 0261 NMVariantMapList listOfPeers = qdbus_cast<NMVariantMapList>(it.value()); 0262 0263 for (const QVariantMap &map : listOfPeers) { 0264 const QString str = QStringLiteral("%1.%2.%3") 0265 .arg(QLatin1String(NM_SETTING_WIREGUARD_PEERS)) 0266 .arg(map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)).toString()) 0267 .arg(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)); 0268 ret.insert(str, map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)).toString()); 0269 } 0270 } 0271 ++it; 0272 } 0273 0274 return ret; 0275 } 0276 0277 QStringList NetworkManager::WireGuardSetting::needSecrets(bool requestNew) const 0278 { 0279 QStringList secrets; 0280 0281 if (!privateKeyFlags().testFlag(Setting::NotRequired)) { 0282 if (privateKey().isEmpty() || requestNew) { 0283 secrets << QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY); 0284 } 0285 } 0286 0287 for (const QVariantMap &map : peers()) { 0288 const QString presharedKey = map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)).toString(); 0289 SecretFlags preSharedKeyFlags = (SecretFlags)map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS)).toInt(); 0290 0291 if (!presharedKey.isEmpty()) { 0292 continue; 0293 } 0294 0295 if (preSharedKeyFlags.testFlag(Setting::NotRequired)) { 0296 continue; 0297 } 0298 0299 const QString str = QStringLiteral("%1.%2.%3") 0300 .arg(QLatin1String(NM_SETTING_WIREGUARD_PEERS)) 0301 .arg(map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PUBLIC_KEY)).toString()) 0302 .arg(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY)); 0303 secrets << str; 0304 } 0305 0306 return secrets; 0307 } 0308 0309 void NetworkManager::WireGuardSetting::fromMap(const QVariantMap &setting) 0310 { 0311 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_FWMARK))) { 0312 setFwmark(setting.value(QLatin1String(NM_SETTING_WIREGUARD_FWMARK)).toInt()); 0313 } 0314 0315 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_LISTEN_PORT))) { 0316 setListenPort(setting.value(QLatin1String(NM_SETTING_WIREGUARD_LISTEN_PORT)).toInt()); 0317 } 0318 0319 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_MTU))) { 0320 setMtu(setting.value(QLatin1String(NM_SETTING_WIREGUARD_MTU)).toInt()); 0321 } 0322 0323 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_PEER_ROUTES))) { 0324 setPeerRoutes(setting.value(QLatin1String(NM_SETTING_WIREGUARD_PEER_ROUTES)).toBool()); 0325 } 0326 0327 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_PEERS))) { 0328 setPeers(qdbus_cast<NMVariantMapList>(setting.value(QLatin1String(NM_SETTING_WIREGUARD_PEERS)))); 0329 } 0330 0331 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY))) { 0332 setPrivateKey(setting.value(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY)).toString()); 0333 } 0334 0335 if (setting.contains(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS))) { 0336 setPrivateKeyFlags((SecretFlags)setting.value(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS)).toInt()); 0337 } 0338 } 0339 0340 QVariantMap NetworkManager::WireGuardSetting::toMap() const 0341 { 0342 QVariantMap setting; 0343 0344 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_FWMARK), fwmark()); 0345 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_LISTEN_PORT), listenPort()); 0346 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_MTU), mtu()); 0347 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_PEER_ROUTES), peerRoutes()); 0348 0349 if (!peers().isEmpty()) { 0350 // FIXME we seem to have SecretFlags as an int, but NM expects an uint, while this is not 0351 // problem for rest of *-flags properties, it's problem for "preshared-key" which NM handless 0352 // as GVariant and asks for "u" when getting it's value 0353 NMVariantMapList fixedPeers = peers(); 0354 for (QVariantMap &map : fixedPeers) { 0355 if (map.contains(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS))) { 0356 map.insert(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS), 0357 map.value(QLatin1String(NM_WIREGUARD_PEER_ATTR_PRESHARED_KEY_FLAGS)).toUInt()); 0358 } 0359 } 0360 0361 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_PEERS), QVariant::fromValue(fixedPeers)); 0362 } 0363 0364 if (!privateKey().isEmpty()) { 0365 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY), privateKey()); 0366 } 0367 setting.insert(QLatin1String(NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS), (int)privateKeyFlags()); 0368 0369 return setting; 0370 } 0371 0372 QDebug NetworkManager::operator<<(QDebug dbg, const NetworkManager::WireGuardSetting &setting) 0373 { 0374 dbg.nospace() << "type: " << setting.typeAsString(setting.type()) << '\n'; 0375 dbg.nospace() << "initialized: " << !setting.isNull() << '\n'; 0376 0377 dbg.nospace() << NM_SETTING_WIREGUARD_FWMARK << ": " << setting.fwmark() << '\n'; 0378 dbg.nospace() << NM_SETTING_WIREGUARD_LISTEN_PORT << ": " << setting.listenPort() << '\n'; 0379 dbg.nospace() << NM_SETTING_WIREGUARD_MTU << ": " << setting.mtu() << '\n'; 0380 dbg.nospace() << NM_SETTING_WIREGUARD_PEER_ROUTES << ": " << setting.peerRoutes() << '\n'; 0381 dbg.nospace() << NM_SETTING_WIREGUARD_PEERS << ": " << setting.peers() << '\n'; 0382 dbg.nospace() << NM_SETTING_WIREGUARD_PRIVATE_KEY << ": " << setting.privateKey() << '\n'; 0383 dbg.nospace() << NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS << ": " << setting.privateKeyFlags() << '\n'; 0384 0385 return dbg.maybeSpace(); 0386 }