KIO::AuthInfo KPasswdServer::checkAuthInfo(KIO::AuthInfo info, long windowId, unsigned long usertime) { kdDebug(130) << "KPasswdServer::checkAuthInfo: User= "******", WindowId = " << windowId << endl; if( usertime != 0 ) kapp->updateUserTimestamp( usertime ); QString key = createCacheKey(info); Request *request = m_authPending.first(); QString path2 = info.url.directory(false, false); for(; request; request = m_authPending.next()) { if (request->key != key) continue; if (info.verifyPath) { QString path1 = request->info.url.directory(false, false); if (!path2.startsWith(path1)) continue; } request = new Request; request->client = callingDcopClient(); request->transaction = request->client->beginTransaction(); request->key = key; request->info = info; m_authWait.append(request); return info; } const AuthInfo *result = findAuthInfoItem(key, info); if (!result || result->isCanceled) { if (!result && (info.username.isEmpty() || info.password.isEmpty()) && !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::PasswordFolder(), makeWalletKey(key, info.realmValue))) { QMap<QString, QString> knownLogins; if (openWallet(windowId)) { if (readFromWallet(m_wallet, key, info.realmValue, info.username, info.password, info.readOnly, knownLogins)) { info.setModified(true); return info; } } } info.setModified(false); return info; } updateAuthExpire(key, result, windowId, false); return copyAuthInfo(result); }
static bool storeInWallet( KWallet::Wallet* wallet, const QString& key, const KIO::AuthInfo &info ) { if ( !wallet->hasFolder( KWallet::Wallet::PasswordFolder() ) ) if ( !wallet->createFolder( KWallet::Wallet::PasswordFolder() ) ) return false; wallet->setFolder( KWallet::Wallet::PasswordFolder() ); // Before saving, check if there's already an entry with this login. // If so, replace it (with the new password). Otherwise, add a new entry. typedef QMap<QString,QString> Map; int entryNumber = 1; Map map; QString walletKey = makeWalletKey( key, info.realmValue ); kdDebug(130) << "storeInWallet: walletKey=" << walletKey << " reading existing map" << endl; if ( wallet->readMap( walletKey, map ) == 0 ) { Map::ConstIterator end = map.end(); Map::ConstIterator it = map.find( "login" ); while ( it != end ) { if ( it.data() == info.username ) { break; // OK, overwrite this entry } it = map.find( QString( "login-" ) + QString::number( ++entryNumber ) ); } // If no entry was found, create a new entry - entryNumber is set already. } const QString loginKey = makeMapKey( "login", entryNumber ); const QString passwordKey = makeMapKey( "password", entryNumber ); kdDebug(130) << "storeInWallet: writing to " << loginKey << "," << passwordKey << endl; // note the overwrite=true by default map.insert( loginKey, info.username ); map.insert( passwordKey, info.password ); wallet->writeMap( walletKey, map ); return true; }
static bool readFromWallet(KWallet::Wallet *wallet, const QString &key, const QString &realm, QString &username, QString &password, bool userReadOnly, QMap< QString, QString > &knownLogins) { // kdDebug(130) << "readFromWallet: key=" << key << " username="******" password="******" userReadOnly=" << userReadOnly // << " realm=" << realm << endl; if(wallet->hasFolder(KWallet::Wallet::PasswordFolder())) { wallet->setFolder(KWallet::Wallet::PasswordFolder()); QMap< QString, QString > map; if(wallet->readMap(makeWalletKey(key, realm), map) == 0) { typedef QMap< QString, QString > Map; int entryNumber = 1; Map::ConstIterator end = map.end(); Map::ConstIterator it = map.find("login"); while(it != end) { // kdDebug(130) << "readFromWallet: found " << it.key() << "=" << it.data() << endl; Map::ConstIterator pwdIter = map.find(makeMapKey("password", entryNumber)); if(pwdIter != end) { if(it.data() == username) password = pwdIter.data(); knownLogins.insert(it.data(), pwdIter.data()); } it = map.find(QString("login-") + QString::number(++entryNumber)); } // kdDebug(130) << knownLogins.count() << " known logins" << endl; if(!userReadOnly && !knownLogins.isEmpty() && username.isEmpty()) { // Pick one, any one... username = knownLogins.begin().key(); password = knownLogins.begin().data(); // kdDebug(130) << "readFromWallet: picked the first one : " << username << endl; } return true; } } return false; }
void KPasswdServer::processRequest() { Request *request = m_authPending.first(); if(!request) return; KIO::AuthInfo &info = request->info; kdDebug(130) << "KPasswdServer::processRequest: User= "******", Message= " << info.prompt << endl; const AuthInfo *result = findAuthInfoItem(request->key, request->info); if(result && (request->seqNr < result->seqNr)) { kdDebug(130) << "KPasswdServer::processRequest: auto retry!" << endl; if(result->isCanceled) { info.setModified(false); } else { updateAuthExpire(request->key, result, request->windowId, false); info = copyAuthInfo(result); } } else { m_seqNr++; bool askPw = request->prompt; if(result && !info.username.isEmpty() && !request->errorMsg.isEmpty()) { QString prompt = request->errorMsg; prompt += i18n(" Do you want to retry?"); int dlgResult = KMessageBox::warningContinueCancelWId(request->windowId, prompt, i18n("Authentication"), i18n("Retry")); if(dlgResult != KMessageBox::Continue) askPw = false; } int dlgResult = QDialog::Rejected; if(askPw) { QString username = info.username; QString password = info.password; bool hasWalletData = false; QMap< QString, QString > knownLogins; if((username.isEmpty() || password.isEmpty()) && !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::PasswordFolder(), makeWalletKey(request->key, info.realmValue))) { // no login+pass provided, check if kwallet has one if(openWallet(request->windowId)) hasWalletData = readFromWallet(m_wallet, request->key, info.realmValue, username, password, info.readOnly, knownLogins); } KIO::PasswordDialog dlg(info.prompt, username, info.keepPassword); if(info.caption.isEmpty()) dlg.setPlainCaption(i18n("Authorization Dialog")); else dlg.setPlainCaption(info.caption); if(!info.comment.isEmpty()) dlg.addCommentLine(info.commentLabel, info.comment); if(!password.isEmpty()) dlg.setPassword(password); if(info.readOnly) dlg.setUserReadOnly(true); else dlg.setKnownLogins(knownLogins); if(hasWalletData) dlg.setKeepPassword(true); #ifdef Q_WS_X11 XSetTransientForHint(qt_xdisplay(), dlg.winId(), request->windowId); #endif dlgResult = dlg.exec(); if(dlgResult == QDialog::Accepted) { info.username = dlg.username(); info.password = dlg.password(); info.keepPassword = dlg.keepPassword(); // When the user checks "keep password", that means: // * if the wallet is enabled, store it there for long-term, and in kpasswdserver // only for the duration of the window (#92928) // * otherwise store in kpasswdserver for the duration of the KDE session. if(info.keepPassword) { if(openWallet(request->windowId)) { if(storeInWallet(m_wallet, request->key, info)) // password is in wallet, don't keep it in memory after window is closed info.keepPassword = false; } } } } if(dlgResult != QDialog::Accepted) { addAuthInfoItem(request->key, info, 0, m_seqNr, true); info.setModified(false); } else { addAuthInfoItem(request->key, info, request->windowId, m_seqNr, false); info.setModified(true); } } QCString replyType; QByteArray replyData; QDataStream stream2(replyData, IO_WriteOnly); stream2 << info << m_seqNr; replyType = "KIO::AuthInfo"; request->client->endTransaction(request->transaction, replyType, replyData); m_authPending.remove((unsigned int)0); // Check all requests in the wait queue. for(Request *waitRequest = m_authWait.first(); waitRequest;) { bool keepQueued = false; QString key = waitRequest->key; request = m_authPending.first(); QString path2 = waitRequest->info.url.directory(false, false); for(; request; request = m_authPending.next()) { if(request->key != key) continue; if(info.verifyPath) { QString path1 = request->info.url.directory(false, false); if(!path2.startsWith(path1)) continue; } keepQueued = true; break; } if(keepQueued) { waitRequest = m_authWait.next(); } else { const AuthInfo *result = findAuthInfoItem(waitRequest->key, waitRequest->info); QCString replyType; QByteArray replyData; QDataStream stream2(replyData, IO_WriteOnly); if(!result || result->isCanceled) { waitRequest->info.setModified(false); stream2 << waitRequest->info; } else { updateAuthExpire(waitRequest->key, result, waitRequest->windowId, false); KIO::AuthInfo info = copyAuthInfo(result); stream2 << info; } replyType = "KIO::AuthInfo"; waitRequest->client->endTransaction(waitRequest->transaction, replyType, replyData); m_authWait.remove(); waitRequest = m_authWait.current(); } } if(m_authPending.count()) QTimer::singleShot(0, this, SLOT(processRequest())); }