KWallet

kwalletd/main.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2008 Michael Leupold <lemma@confuego.org>
4 SPDX-FileCopyrightText: 2014 Alex Fiestas <afiestas@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-only
7*/
8
9#include "kwalletd_debug.h"
10#include <KAboutData>
11#include <KConfig>
12#include <KConfigGroup>
13#include <KCrash>
14#include <KDBusService>
15#include <KLocalizedString>
16
17#include <QApplication>
18#include <QCommandLineParser>
19#include <QIcon>
20#include <QSessionManager>
21#include <QString>
22
23#include <stdio.h>
24
25#include "backend/kwalletbackend.h" //For the hash size
26#include "kwalletd.h"
27#include "kwalletd_version.h"
28#include "kwalletfreedesktopservice.h"
29
30#ifndef Q_OS_WIN
31#include <sys/socket.h>
32#include <sys/types.h>
33#include <sys/un.h>
34#include <unistd.h>
35
36#define BSIZE 1000
37static int pipefd = 0;
38static int socketfd = 0;
39#endif
40
41static bool isWalletEnabled()
42{
43 KConfig cfg(QStringLiteral("kwalletrc"));
44 KConfigGroup walletGroup(&cfg, "Wallet");
45 return walletGroup.readEntry("Enabled", true);
46}
47
48#ifndef Q_OS_WIN
49// Waits until the PAM_MODULE sends the hash
50static char *waitForHash()
51{
52 qCDebug(KWALLETD_LOG) << "kwalletd5: Waiting for hash on" << pipefd;
53 int totalRead = 0;
54 int readBytes = 0;
55 int attempts = 0;
56 char *buf = (char *)malloc(sizeof(char) * PBKDF2_SHA512_KEYSIZE);
57 memset(buf, '\0', PBKDF2_SHA512_KEYSIZE);
58 while (totalRead != PBKDF2_SHA512_KEYSIZE) {
59 readBytes = read(pipefd, buf + totalRead, PBKDF2_SHA512_KEYSIZE - totalRead);
60 if (readBytes == -1 || attempts > 5) {
61 free(buf);
62 return nullptr;
63 }
64 totalRead += readBytes;
65 ++attempts;
66 }
67
68 close(pipefd);
69 return buf;
70}
71
72// Waits until startkde sends the environment variables
73static int waitForEnvironment()
74{
75 qCDebug(KWALLETD_LOG) << "kwalletd5: waitingForEnvironment on:" << socketfd;
76
77 int s2;
78 struct sockaddr_un remote;
79 socklen_t t = sizeof(remote);
80 if ((s2 = accept(socketfd, (struct sockaddr *)&remote, &t)) == -1) {
81 qCWarning(KWALLETD_LOG) << "kwalletd5: Couldn't accept incoming connection";
82 return -1;
83 }
84 qCDebug(KWALLETD_LOG) << "kwalletd5: client connected";
85
86 char str[BSIZE] = {'\0'};
87
88 int chop = 0;
89 FILE *s3 = fdopen(dup(s2), "r");
90 while (!feof(s3)) {
91 if (fgets(str, BSIZE, s3)) {
92 chop = strlen(str) - 1;
93 if (str[chop] == '\n') {
94 str[chop] = '\0';
95 }
96 putenv(strdup(str));
97 }
98 }
99 fclose(s3);
100
101 qCDebug(KWALLETD_LOG) << "kwalletd5: client disconnected";
102 close(socketfd);
103 return 1;
104}
105
106char *checkPamModule(int argc, char **argv)
107{
108 qCDebug(KWALLETD_LOG) << "kwalletd5: Checking for pam module";
109 char *hash = nullptr;
110 int x = 1;
111 for (; x < argc; ++x) {
112 if (strcmp(argv[x], "--pam-login") != 0) {
113 continue;
114 }
115 qCDebug(KWALLETD_LOG) << "kwalletd5: Got pam-login param";
116 argv[x] = nullptr;
117 x++;
118 // We need at least 2 extra arguments after --pam-login
119 if (x + 1 > argc) {
120 qCWarning(KWALLETD_LOG) << "kwalletd5: Invalid arguments (less than needed)";
121 return nullptr;
122 }
123
124 // first socket for the hash, comes from a pipe
125 pipefd = atoi(argv[x]);
126 argv[x] = nullptr;
127 x++;
128 // second socket for environment, comes from a localsocket
129 socketfd = atoi(argv[x]);
130 argv[x] = nullptr;
131 break;
132 }
133
134 if (!pipefd || !socketfd) {
135 qCWarning(KWALLETD_LOG) << "Lacking a socket, pipe:" << pipefd << "env:" << socketfd;
136 return nullptr;
137 }
138
139 hash = waitForHash();
140
141 if (hash == nullptr || waitForEnvironment() == -1) {
142 qCWarning(KWALLETD_LOG) << "kwalletd5: Hash or environment not received";
143 free(hash);
144 return nullptr;
145 }
146
147 return hash;
148}
149#endif
150
151int main(int argc, char **argv)
152{
153 char *hash = nullptr;
154#ifndef Q_OS_WIN
155 if (getenv("PAM_KWALLET5_LOGIN")) {
156 hash = checkPamModule(argc, argv);
157 }
158#endif
159
160 QApplication app(argc, argv);
161 app.setWindowIcon(QIcon::fromTheme(QStringLiteral("kwalletmanager")));
162
163 // this kwalletd5 program should be able to start with KDE4's kwalletd
164 // using kwalletd name would prevent KDBusService unique instance to initialize
165 // so we setApplicationName("kwalletd6")
166 KAboutData aboutdata("kwalletd6",
167 i18n("KDE Wallet Service"),
168 KWALLETD_VERSION_STRING,
169 i18n("KDE Wallet Service"),
171 i18n("(C) 2002-2013, The KDE Developers"));
172 aboutdata.addAuthor(i18n("Valentin Rusu"), i18n("Former Maintainer, GPG backend support"), QStringLiteral("kde@rusu.info"));
173 aboutdata.addAuthor(i18n("Michael Leupold"), i18n("Former Maintainer"), QStringLiteral("lemma@confuego.org"));
174 aboutdata.addAuthor(i18n("George Staikos"), i18n("Former maintainer"), QStringLiteral("staikos@kde.org"));
175 aboutdata.addAuthor(i18n("Thiago Maceira"), i18n("D-Bus Interface"), QStringLiteral("thiago@kde.org"));
176
178
180
181 KDBusService dbusUniqueInstance(KDBusService::Unique);
182
183 // NOTE: the command should be parsed only after KDBusService instantiation
184 QCommandLineParser cmdParser;
185 aboutdata.setupCommandLine(&cmdParser);
186 cmdParser.process(app);
187
188 app.setQuitOnLastWindowClosed(false);
189 auto disableSessionManagement = [](QSessionManager &sm) {
190 sm.setRestartHint(QSessionManager::RestartNever);
191 };
192 QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement);
193 QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement);
194
195 // check if kwallet is disabled
196 if (!isWalletEnabled()) {
197 qCDebug(KWALLETD_LOG) << "kwalletd is disabled!";
198
199 /* Do not keep dbus-daemon waiting for the org.freedesktop.secrets if kwallet is disabled */
200 KWalletFreedesktopService(nullptr);
201
202 return (0);
203 }
204
205 KWalletD walletd;
206 qCDebug(KWALLETD_LOG) << "kwalletd6 started";
207
208#ifndef Q_OS_WIN
209 if (hash) {
210 QByteArray passHash(hash, PBKDF2_SHA512_KEYSIZE);
211 int wallet = walletd.pamOpen(KWallet::Wallet::LocalWallet(), passHash, 0);
212 if (wallet < 0) {
213 qCWarning(KWALLETD_LOG) << "Wallet failed to get opened by PAM, error code is" << wallet;
214 } else {
215 qCDebug(KWALLETD_LOG) << "Wallet opened by PAM";
216 }
217 free(hash);
218 }
219#endif
220
221 return app.exec();
222}
static void setApplicationData(const KAboutData &aboutData)
static const QString LocalWallet()
The name of the wallet used to store local passwords.
Definition kwallet.cpp:58
QString i18n(const char *text, const TYPE &arg...)
KCRASH_EXPORT void initialize()
QVariant read(const QByteArray &data, int versionOverride=0)
KGuiItem close()
void process(const QCoreApplication &app)
void commitDataRequest(QSessionManager &manager)
void saveStateRequest(QSessionManager &manager)
QIcon fromTheme(const QString &name)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:10:15 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.