mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 10:52:51 +00:00
205 lines
7.4 KiB
C++
205 lines
7.4 KiB
C++
/*************************************************************************************
|
|
* Copyright (C) 2014 by Alejandro Fiestas Olivares <afiestas@kde.org> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU General Public License *
|
|
* as published by the Free Software Foundation; either version 2 *
|
|
* of the License, or (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the Free Software *
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
|
|
*************************************************************************************/
|
|
|
|
#include "kwalletexecuter.h"
|
|
|
|
#include <unistd.h>
|
|
#include <sys/un.h>
|
|
#include <sys/socket.h>
|
|
|
|
#include <QTest>
|
|
#include <QtCore/QTimer>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QDebug>
|
|
#include <QtCore/QEventLoop>
|
|
#include <QtNetwork/QLocalSocket>
|
|
#include <QtDBus/QDBusMessage>
|
|
#include <QtDBus/QDBusConnection>
|
|
#include <QtDBus/QDBusServiceWatcher>
|
|
#include <QtDBus/QDBusConnectionInterface>
|
|
#include <kconfig.h>
|
|
#include <kconfiggroup.h>
|
|
#include <kstandarddirs.h>
|
|
|
|
extern char **environ;
|
|
|
|
KWalletExecuter::KWalletExecuter(QObject* parent): QObject(parent)
|
|
{
|
|
// Make sure wallet is enabled, otherwise test will fail
|
|
KConfig cfg("kwalletrc");
|
|
KConfigGroup cg( &cfg, "Wallet");
|
|
cg.writeEntry("First Use", false);
|
|
cg.writeEntry("Enabled", true);
|
|
}
|
|
|
|
void KWalletExecuter::pamOpen()
|
|
{
|
|
QDBusMessage msg =
|
|
QDBusMessage::createMethodCall("org.kde.kwalletd", "/modules/kwalletd", "org.kde.KWallet", "open");
|
|
QVariantList args;
|
|
qlonglong wid = 0;
|
|
args << QLatin1String("kdewallet") << wid << QLatin1String("buh");
|
|
msg.setArguments(args);
|
|
const QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
|
|
|
|
QVERIFY2(reply.type() != QDBusMessage::ErrorMessage, reply.errorMessage().toLocal8Bit());
|
|
m_handler = reply.arguments().first().toInt();
|
|
if (m_handler <= 0) {
|
|
qFatal("Couldn't open the wallet via dbus");//We don't want the test to continue
|
|
}
|
|
}
|
|
|
|
void KWalletExecuter::pamWrite(const QString &value) const
|
|
{
|
|
QDBusMessage msg =
|
|
QDBusMessage::createMethodCall("org.kde.kwalletd", "/modules/kwalletd", "org.kde.KWallet", "writePassword");
|
|
QVariantList args;
|
|
args << m_handler
|
|
<< QLatin1String("Passwords")
|
|
<< QLatin1String("foo")
|
|
<< value
|
|
<< QLatin1String("buh");
|
|
msg.setArguments(args);
|
|
const QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
|
|
|
|
QVERIFY2(reply.type() != QDBusMessage::ErrorMessage, reply.errorMessage().toLocal8Bit());
|
|
int ret = reply.arguments().first().toInt();
|
|
QCOMPARE(ret, 0);
|
|
}
|
|
|
|
void KWalletExecuter::pamRead(const QString &value) const
|
|
{
|
|
QDBusMessage msg =
|
|
QDBusMessage::createMethodCall("org.kde.kwalletd", "/modules/kwalletd", "org.kde.KWallet", "readPassword");
|
|
QVariantList args;
|
|
args << m_handler
|
|
<< QLatin1String("Passwords")
|
|
<< QLatin1String("foo")
|
|
<< QLatin1String("buh");
|
|
msg.setArguments(args);
|
|
const QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
|
|
|
|
QVERIFY2(reply.type() != QDBusMessage::ErrorMessage, reply.errorMessage().toLocal8Bit());
|
|
const QString password = reply.arguments().first().toString();
|
|
QCOMPARE(password, value);
|
|
}
|
|
|
|
void KWalletExecuter::execute_kwallet(int toWalletPipe[2], int envSocket)
|
|
{
|
|
int x = 3;
|
|
//Close fd that are not of interest of kwallet
|
|
for (; x < 64; ++x) {
|
|
if (x != toWalletPipe[0] && x != envSocket) {
|
|
close (x);
|
|
}
|
|
}
|
|
|
|
close (toWalletPipe[1]);
|
|
|
|
char pipeInt[2];
|
|
sprintf(pipeInt, "%d", toWalletPipe[0]);
|
|
char sockIn[2];
|
|
sprintf(sockIn, "%d", envSocket);
|
|
|
|
qDebug() << "Executing kwalletd";
|
|
QByteArray wallet = KStandardDirs::findExe("kwalletd").toLocal8Bit();
|
|
char *args[] = {wallet.data(), (char*)"--pam-login", pipeInt, sockIn, NULL};
|
|
execve(args[0], args, environ);
|
|
qFatal("Couldn't execute kwalletd");
|
|
}
|
|
|
|
void KWalletExecuter::execute()
|
|
{
|
|
//Preparing sockets, we will share them with kwalletd
|
|
int toWalletPipe[2] = { -1, -1};
|
|
if (pipe(toWalletPipe) < 0) {
|
|
qFatal("Couldn't craete pipes");
|
|
}
|
|
|
|
int envSocket;
|
|
if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
|
qFatal("Couldn't create socket");
|
|
}
|
|
|
|
QByteArray sock = KStandardDirs::locateLocal("socket", QLatin1String("test.socket")).toLocal8Bit();
|
|
struct sockaddr_un local;
|
|
local.sun_family = AF_UNIX;
|
|
strcpy(local.sun_path, sock.constData());
|
|
unlink(local.sun_path);//Just in case it exists from a previous login
|
|
|
|
int len;
|
|
len = strlen(local.sun_path) + sizeof(local.sun_family);
|
|
if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
|
|
qFatal("Couldn't bind the socket");
|
|
}
|
|
|
|
if (listen(envSocket, 5) == -1) {
|
|
qFatal("Couldn't listen into the socket");
|
|
}
|
|
|
|
qputenv("PAM_KWALLET_LOGIN", "1");
|
|
pid_t pid;
|
|
switch (pid = fork ()) {
|
|
case -1: {
|
|
qFatal("Couldn't fork to execv kwalletd");
|
|
break;
|
|
}
|
|
|
|
// Child fork, will contain kwalletd
|
|
case 0: {
|
|
execute_kwallet(toWalletPipe, envSocket);
|
|
/* Should never be reached */
|
|
break;
|
|
}
|
|
|
|
// Parent
|
|
default:
|
|
break;
|
|
};
|
|
|
|
close(toWalletPipe[0]);//Read end of the pipe, we will only use the write
|
|
|
|
QByteArray hash =
|
|
QByteArray::fromHex("1f1e7736894243657ef4a5274211b9a62703494c286e1699418a36e7ecf31d37319644db63d9fb26eb57cd9b7fea3e88bc18312480ba54f4");
|
|
write(toWalletPipe[1], hash.constData(), 56);
|
|
|
|
QLocalSocket *socket = new QLocalSocket(this);
|
|
socket->connectToServer(sock);
|
|
//No need to send any environment vars, the env is already ok
|
|
socket->close();
|
|
|
|
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwalletd")) {
|
|
qDebug() << "AAAAAAAA";
|
|
QEventLoop loop;
|
|
QTimer::singleShot(30000, &loop, SLOT(quit()));
|
|
QDBusServiceWatcher *watcher = new QDBusServiceWatcher("org.kde.kwalletd",
|
|
QDBusConnection::sessionBus(),
|
|
QDBusServiceWatcher::WatchForRegistration);
|
|
connect(watcher, SIGNAL(serviceRegistered(QString)), &loop, SLOT(quit()));
|
|
loop.exec();
|
|
}
|
|
}
|
|
|
|
void KWalletExecuter::cleanupTestCase()
|
|
{
|
|
QDBusMessage msg =
|
|
QDBusMessage::createMethodCall("org.kde.kwalletd", "/MainApplication", "org.kde.KApplication", "quit");
|
|
const QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
|
|
|
|
Q_ASSERT(reply.type() != QDBusMessage::ErrorMessage);
|
|
}
|