File indexing completed on 2024-04-14 15:05:31
0001 /*************************************************************************** 0002 This is the wallet manager of Smb4K. 0003 ------------------- 0004 begin : Sa Dez 27 2008 0005 copyright : (C) 2008-2019 by Alexander Reinholdt 0006 email : alexander.reinholdt@kdemail.net 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, but * 0016 * WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0018 * General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the * 0022 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston,* 0023 * MA 02110-1335, USA * 0024 ***************************************************************************/ 0025 0026 #ifdef HAVE_CONFIG_H 0027 #include <config.h> 0028 #endif 0029 0030 // application specific includes 0031 #include "smb4kwalletmanager.h" 0032 #include "smb4kwalletmanager_p.h" 0033 #include "smb4ksettings.h" 0034 #include "smb4kauthinfo.h" 0035 #include "smb4khomesshareshandler.h" 0036 #include "smb4kglobal.h" 0037 #include "smb4knotification.h" 0038 #include "smb4khost.h" 0039 #include "smb4kshare.h" 0040 0041 // Qt includes 0042 #include <QPointer> 0043 #include <QTest> 0044 #include <QApplication> 0045 0046 // KDE includes 0047 0048 using namespace Smb4KGlobal; 0049 0050 Q_GLOBAL_STATIC(Smb4KWalletManagerStatic, p); 0051 0052 0053 0054 Smb4KWalletManager::Smb4KWalletManager(QObject *parent) 0055 : QObject(parent), d(new Smb4KWalletManagerPrivate) 0056 { 0057 d->wallet = 0; 0058 } 0059 0060 0061 Smb4KWalletManager::~Smb4KWalletManager() 0062 { 0063 } 0064 0065 0066 Smb4KWalletManager *Smb4KWalletManager::self() 0067 { 0068 return &p->instance; 0069 } 0070 0071 0072 void Smb4KWalletManager::init() 0073 { 0074 if (useWalletSystem()) 0075 { 0076 // 0077 // Get a pointer to the wallet, if we do not have one yet 0078 // 0079 if (!d->wallet) 0080 { 0081 // 0082 // Open the wallet synchronously. 0083 // 0084 d->wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), QApplication::activeWindow() ? QApplication::activeWindow()->winId() : 0); 0085 0086 // 0087 // Check if the walled was opened successfully and set the 0088 // right folder, if it was 0089 // 0090 if (d->wallet) 0091 { 0092 if (d->wallet->isOpen()) 0093 { 0094 if (!d->wallet->hasFolder("Smb4K")) 0095 { 0096 d->wallet->createFolder("Smb4K"); 0097 d->wallet->setFolder("Smb4K"); 0098 } 0099 else 0100 { 0101 d->wallet->setFolder("Smb4K"); 0102 } 0103 } 0104 else 0105 { 0106 Smb4KNotification::credentialsNotAccessible(); 0107 } 0108 } 0109 else 0110 { 0111 delete d->wallet; 0112 d->wallet = 0; 0113 0114 Smb4KNotification::openingWalletFailed(KWallet::Wallet::NetworkWallet()); 0115 } 0116 } 0117 } 0118 else 0119 { 0120 if (d->wallet) 0121 { 0122 // 0123 // Close the wallet, if Smb4K is the only application that 0124 // is using it. Thus, use force=false, otherwise it will definitely 0125 // be closed. 0126 // 0127 d->wallet->closeWallet(KWallet::Wallet::NetworkWallet(), false); 0128 0129 // 0130 // Delete the wallet and set it to 0. 0131 // 0132 delete d->wallet; 0133 d->wallet = 0; 0134 } 0135 } 0136 0137 emit initialized(); 0138 } 0139 0140 0141 void Smb4KWalletManager::readAuthInfo(const NetworkItemPtr &networkItem) 0142 { 0143 // 0144 // Only do something, if the networkItem is not null 0145 // 0146 if (networkItem) 0147 { 0148 // 0149 // Initialize the wallet manager. 0150 // 0151 init(); 0152 0153 // 0154 // Proceed if the wallet is open 0155 // 0156 if (walletIsOpen()) 0157 { 0158 // 0159 // Get the list of entries 0160 // 0161 QStringList entryList = d->wallet->entryList(); 0162 0163 // 0164 // Create the map to store the authentication information 0165 // 0166 QMap<QString, QString> authInfoMap; 0167 0168 // 0169 // Now loop through the stored credentials and make a case insensitive comparison 0170 // with the URL of the network item. 0171 // 0172 for (const QString &entry : entryList) 0173 { 0174 if (networkItem->type() == Host) 0175 { 0176 if (QString::compare(entry, networkItem->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), Qt::CaseInsensitive) == 0 || 0177 QString::compare(entry, networkItem->url().toString(QUrl::RemoveScheme|QUrl::RemoveUserInfo|QUrl::RemovePort), Qt::CaseInsensitive) == 0) 0178 { 0179 d->wallet->readMap(entry, authInfoMap); 0180 break; 0181 } 0182 } 0183 else if (networkItem->type() == Share) 0184 { 0185 // 0186 // Cast the network item. We need some share specific info 0187 // 0188 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0189 0190 if (share) 0191 { 0192 // 0193 // Process normal and 'homes' shares differently 0194 // 0195 if (!share->isHomesShare()) 0196 { 0197 // 0198 // Prefer the credentials for the share. Use the ones for the 0199 // host as fallback. 0200 // 0201 if (QString::compare(entry, share->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), Qt::CaseInsensitive) == 0 || 0202 QString::compare(entry, share->url().toString(QUrl::RemoveScheme|QUrl::RemoveUserInfo|QUrl::RemovePort), Qt::CaseInsensitive) == 0) 0203 { 0204 d->wallet->readMap(entry, authInfoMap); 0205 break; 0206 } 0207 else if (QString::compare(entry, share->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort|QUrl::RemovePath), Qt::CaseInsensitive) == 0 || 0208 QString::compare(entry, share->url().toString(QUrl::RemoveScheme|QUrl::RemoveUserInfo|QUrl::RemovePort|QUrl::RemovePath), Qt::CaseInsensitive) == 0) 0209 { 0210 d->wallet->readMap(entry, authInfoMap); 0211 } 0212 } 0213 else 0214 { 0215 // 0216 // Prefer the credentials for the share. Use the ones for the 0217 // host as fallback. 0218 // 0219 if (QString::compare(entry, share->homeUrl().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), Qt::CaseInsensitive) == 0 || 0220 QString::compare(entry, share->homeUrl().toString(QUrl::RemoveScheme|QUrl::RemoveUserInfo|QUrl::RemovePort), Qt::CaseInsensitive) == 0) 0221 { 0222 d->wallet->readMap(entry, authInfoMap); 0223 break; 0224 } 0225 else if (QString::compare(entry, share->homeUrl().toString(QUrl::RemoveUserInfo|QUrl::RemovePort|QUrl::RemovePath), Qt::CaseInsensitive) == 0 || 0226 QString::compare(entry, share->homeUrl().toString(QUrl::RemoveScheme|QUrl::RemoveUserInfo|QUrl::RemovePort|QUrl::RemovePath), Qt::CaseInsensitive) == 0) 0227 { 0228 d->wallet->readMap(entry, authInfoMap); 0229 } 0230 } 0231 } 0232 } 0233 } 0234 0235 // 0236 // Set the authentication information 0237 // 0238 if (!authInfoMap.isEmpty()) 0239 { 0240 switch (networkItem->type()) 0241 { 0242 case Host: 0243 { 0244 HostPtr host = networkItem.staticCast<Smb4KHost>(); 0245 0246 if (QString::compare(host->workgroupName(), authInfoMap.value("Workgroup"), Qt::CaseInsensitive) == 0) 0247 { 0248 host->setLogin(authInfoMap.value("Login")); 0249 host->setPassword(authInfoMap.value("Password")); 0250 } 0251 0252 break; 0253 } 0254 case Share: 0255 { 0256 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0257 0258 if (QString::compare(share->workgroupName(), authInfoMap.value("Workgroup"), Qt::CaseInsensitive) == 0) 0259 { 0260 share->setLogin(authInfoMap.value("Login")); 0261 share->setPassword(authInfoMap.value("Password")); 0262 } 0263 0264 break; 0265 } 0266 default: 0267 { 0268 break; 0269 } 0270 } 0271 } 0272 else 0273 { 0274 // 0275 // In case the map is empty, set the default login, if it is to be used 0276 // 0277 if (Smb4KSettings::useDefaultLogin()) 0278 { 0279 d->wallet->readMap("DEFAULT_LOGIN", authInfoMap); 0280 0281 switch (networkItem->type()) 0282 { 0283 case Host: 0284 { 0285 HostPtr host = networkItem.staticCast<Smb4KHost>(); 0286 host->setLogin(authInfoMap.value("Login")); 0287 host->setPassword(authInfoMap.value("Password")); 0288 0289 break; 0290 } 0291 case Share: 0292 { 0293 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0294 share->setLogin(authInfoMap.value("Login")); 0295 share->setPassword(authInfoMap.value("Password")); 0296 0297 break; 0298 } 0299 default: 0300 { 0301 break; 0302 } 0303 } 0304 } 0305 } 0306 } 0307 } 0308 } 0309 0310 0311 void Smb4KWalletManager::readDefaultAuthInfo(Smb4KAuthInfo *authInfo) 0312 { 0313 if (authInfo) 0314 { 0315 // 0316 // Initialize the wallet manager. 0317 // 0318 init(); 0319 0320 if (walletIsOpen()) 0321 { 0322 // 0323 // Read the default authentication information from the 0324 // wallet. 0325 // 0326 QMap<QString, QString> authInfoMap; 0327 d->wallet->readMap("DEFAULT_LOGIN", authInfoMap); 0328 0329 if (!authInfoMap.isEmpty()) 0330 { 0331 authInfo->setUserName(authInfoMap.value("Login")); 0332 authInfo->setPassword(authInfoMap.value("Password")); 0333 } 0334 } 0335 } 0336 } 0337 0338 0339 void Smb4KWalletManager::writeAuthInfo(const NetworkItemPtr &networkItem) 0340 { 0341 if (networkItem) 0342 { 0343 // 0344 // Initialize the wallet manager. 0345 // 0346 init(); 0347 0348 if (walletIsOpen()) 0349 { 0350 // 0351 // Handle the network item according to its type 0352 // 0353 switch (networkItem->type()) 0354 { 0355 case Host: 0356 { 0357 // 0358 // Cast the network item 0359 // 0360 HostPtr host = networkItem.staticCast<Smb4KHost>(); 0361 0362 if (host) 0363 { 0364 // 0365 // Write the authentication information to the wallet, if it 0366 // is not empty. 0367 // 0368 if (!host->login().isEmpty() /* allow empty passwords */ && !host->hostName().isEmpty()) 0369 { 0370 // 0371 // Create the map that carries the authentication information 0372 // 0373 QMap<QString, QString> authInfoMap; 0374 0375 // 0376 // Insert login and password 0377 // 0378 authInfoMap.insert("Login", host->login()); 0379 authInfoMap.insert("Password", host->password()); 0380 0381 // 0382 // Enter the workgroup, if it exists 0383 // 0384 if (!host->workgroupName().isEmpty()) 0385 { 0386 authInfoMap.insert("Workgroup", host->workgroupName()); 0387 } 0388 0389 // 0390 // Enter the IP address, if is exists 0391 // 0392 if (host->hasIpAddress()) 0393 { 0394 authInfoMap.insert("IP Address", host->ipAddress()); 0395 } 0396 0397 // 0398 // Write the entry to the wallet 0399 // 0400 d->wallet->writeMap(host->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), authInfoMap); 0401 d->wallet->sync(); 0402 } 0403 } 0404 0405 break; 0406 } 0407 case Share: 0408 { 0409 // 0410 // Cast the network item 0411 // 0412 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0413 0414 if (share) 0415 { 0416 // 0417 // Write the authentication information to the wallet, if it 0418 // is not empty. 0419 // 0420 if (!share->login().isEmpty() /* allow empty passwords */ && !share->hostName().isEmpty()) 0421 { 0422 // 0423 // Create the map that carries the authentication information 0424 // 0425 QMap<QString, QString> authInfoMap; 0426 0427 // 0428 // Insert login and password 0429 // 0430 authInfoMap.insert("Login", share->login()); 0431 authInfoMap.insert("Password", share->password()); 0432 0433 // 0434 // Enter the workgroup, if it exists 0435 // 0436 if (!share->workgroupName().isEmpty()) 0437 { 0438 authInfoMap.insert("Workgroup", share->workgroupName()); 0439 } 0440 0441 // 0442 // Enter the IP address, if is exists 0443 // 0444 if (share->hasHostIpAddress()) 0445 { 0446 authInfoMap.insert("IP Address", share->hostIpAddress()); 0447 } 0448 0449 // 0450 // Write the entry to the wallet 0451 // 0452 if (!share->isHomesShare()) 0453 { 0454 d->wallet->writeMap(share->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), authInfoMap); 0455 } 0456 else 0457 { 0458 d->wallet->writeMap(share->homeUrl().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), authInfoMap); 0459 } 0460 } 0461 } 0462 0463 break; 0464 } 0465 default: 0466 { 0467 break; 0468 } 0469 } 0470 } 0471 } 0472 } 0473 0474 0475 void Smb4KWalletManager::writeDefaultAuthInfo(Smb4KAuthInfo *authInfo) 0476 { 0477 if (authInfo) 0478 { 0479 // 0480 // Initialize the wallet manager. 0481 // 0482 init(); 0483 0484 if (walletIsOpen()) 0485 { 0486 // 0487 // Write the default authentication information to the 0488 // wallet. 0489 // 0490 if (!authInfo->userName().isEmpty() /* allow empty passwords */) 0491 { 0492 QMap<QString, QString> authInfoMap; 0493 authInfoMap.insert("Login", authInfo->userName()); 0494 authInfoMap.insert("Password", authInfo->password()); 0495 0496 d->wallet->writeMap("DEFAULT_LOGIN", authInfoMap); 0497 d->wallet->sync(); 0498 } 0499 } 0500 } 0501 } 0502 0503 0504 bool Smb4KWalletManager::showPasswordDialog(const NetworkItemPtr &networkItem) 0505 { 0506 // 0507 // Define the return value here 0508 // 0509 bool success = false; 0510 0511 // 0512 // Check that the network item is not null 0513 // 0514 if (networkItem) 0515 { 0516 // 0517 // Initialize the wallet manager. 0518 // 0519 init(); 0520 0521 // 0522 // Get the known logins (for homes shares) and read the authentication 0523 // information. 0524 // 0525 QMap<QString, QString> knownLogins; 0526 0527 switch(networkItem->type()) 0528 { 0529 case Share: 0530 { 0531 // 0532 // Cast the network item 0533 // 0534 SharePtr share = networkItem.staticCast<Smb4KShare>(); 0535 0536 // 0537 // If the share is a 'homes' share, read the known logins 0538 // for that share. 0539 // 0540 if (share->isHomesShare()) 0541 { 0542 // 0543 // Get the known logins 0544 // 0545 QStringList users = Smb4KHomesSharesHandler::self()->homesUsers(share); 0546 0547 // 0548 // Read the authentication information for all known logins 0549 // 0550 for (const QString &user : users) 0551 { 0552 // 0553 // Create a temp share 0554 // 0555 SharePtr tempShare = share; 0556 0557 // 0558 // Set the login 0559 // 0560 tempShare->setLogin(user); 0561 0562 // 0563 // Read the authentication information 0564 // 0565 readAuthInfo(tempShare); 0566 0567 // 0568 // Save the authentication data in the map 0569 // 0570 knownLogins.insert(tempShare->login(), tempShare->password()); 0571 0572 // 0573 // Clear the temp share 0574 // 0575 tempShare.clear(); 0576 } 0577 } 0578 else 0579 { 0580 readAuthInfo(networkItem); 0581 } 0582 0583 break; 0584 } 0585 default: 0586 { 0587 readAuthInfo(networkItem); 0588 break; 0589 } 0590 } 0591 0592 // 0593 // Set up the password dialog and show it 0594 // 0595 QPointer<Smb4KPasswordDialog> dlg = new Smb4KPasswordDialog(networkItem, knownLogins, QApplication::activeWindow()); 0596 0597 if (dlg->exec() == Smb4KPasswordDialog::Accepted) 0598 { 0599 // Write the authentication information. 0600 writeAuthInfo(networkItem); 0601 success = true; 0602 } 0603 0604 delete dlg; 0605 } 0606 0607 return success; 0608 } 0609 0610 0611 bool Smb4KWalletManager::useWalletSystem() const 0612 { 0613 return (KWallet::Wallet::isEnabled() && Smb4KSettings::useWallet()); 0614 } 0615 0616 0617 QList<Smb4KAuthInfo *> Smb4KWalletManager::walletEntries() 0618 { 0619 // 0620 // Initialize the wallet manager. 0621 // 0622 init(); 0623 0624 // 0625 // Define the return value 0626 // 0627 QList<Smb4KAuthInfo *> entries; 0628 0629 // 0630 // Only read from the wallet if it is open 0631 // 0632 if (walletIsOpen()) 0633 { 0634 // 0635 // Get all entries from the wallet 0636 // 0637 QStringList entryList = d->wallet->entryList(); 0638 0639 // 0640 // Process the entries 0641 // 0642 for (const QString &entry : entryList) 0643 { 0644 // 0645 // Create a auth info object 0646 // 0647 Smb4KAuthInfo *authInfo = new Smb4KAuthInfo(); 0648 0649 // 0650 // Read the authentication information from the wallet 0651 // 0652 QMap<QString, QString> authInfoMap; 0653 d->wallet->readMap(entry, authInfoMap); 0654 0655 // 0656 // Process the entry 0657 // 0658 if (entry == "DEFAULT_LOGIN") 0659 { 0660 // 0661 // Default login 0662 // 0663 authInfo->setUserName(authInfoMap.value("Login")); 0664 authInfo->setPassword(authInfoMap.value("Password")); 0665 } 0666 else 0667 { 0668 // 0669 // Entry for a specific URL 0670 // 0671 authInfo->setUrl(entry); 0672 authInfo->setIpAddress(authInfoMap.value("IP Address")); 0673 authInfo->setWorkgroupName(authInfoMap.value("Workgroup")); 0674 authInfo->setUserName(authInfoMap.value("Login")); 0675 authInfo->setPassword(authInfoMap.value("Password")); 0676 } 0677 0678 entries << authInfo; 0679 } 0680 } 0681 0682 return entries; 0683 } 0684 0685 0686 void Smb4KWalletManager::writeWalletEntries(const QList<Smb4KAuthInfo *> &entries) 0687 { 0688 // 0689 // Initialize the wallet manager. 0690 // 0691 init(); 0692 0693 // 0694 // Write the list if the wallet is open 0695 // 0696 if (walletIsOpen()) 0697 { 0698 // 0699 // First clear the wallet 0700 // 0701 QStringList entryList = d->wallet->entryList(); 0702 0703 for (const QString &entry : entryList) 0704 { 0705 d->wallet->removeEntry(entry); 0706 } 0707 0708 // 0709 // Now write the new entries to the wallet 0710 // 0711 for (Smb4KAuthInfo *authInfo : entries) 0712 { 0713 QMap<QString, QString> authInfoMap; 0714 0715 if (authInfo->type() == UnknownNetworkItem) 0716 { 0717 // 0718 // Default login 0719 // 0720 authInfoMap.insert("Login", authInfo->userName()); 0721 authInfoMap.insert("Password", authInfo->password()); 0722 0723 // 0724 // Write the default authentication information to the wallet 0725 // 0726 d->wallet->writeMap("DEFAULT_LOGIN", authInfoMap); 0727 } 0728 else 0729 { 0730 // 0731 // Authentication information for a specific URL 0732 // 0733 authInfoMap.insert("IP Address", authInfo->ipAddress()); 0734 authInfoMap.insert("Workgroup", authInfo->workgroupName()); 0735 authInfoMap.insert("Login", authInfo->userName()); 0736 authInfoMap.insert("Password", authInfo->password()); 0737 0738 // 0739 // Write the authentication information to the wallet 0740 // 0741 d->wallet->writeMap(authInfo->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), authInfoMap); 0742 } 0743 0744 // 0745 // Sync the entries to disk 0746 // 0747 d->wallet->sync(); 0748 } 0749 } 0750 } 0751 0752 0753 bool Smb4KWalletManager::walletIsOpen() const 0754 { 0755 return (d->wallet ? (useWalletSystem() && d->wallet->isOpen()) : false); 0756 } 0757