405 lines
16 KiB
Diff
405 lines
16 KiB
Diff
From 1d5aa1d27bff87b2d242ed759cfb2ce15a5c3de7 Mon Sep 17 00:00:00 2001
|
|
From: David Edmundson <kde@davidedmundson.co.uk>
|
|
Date: Sat, 13 Apr 2024 23:30:34 +0100
|
|
Subject: [PATCH] Remove iceauth dependency
|
|
|
|
Previously the tool iceauth was used to write authentication to and from
|
|
the iceauthority file, running a set of commands to manipulate the file.
|
|
|
|
This external dependency is not often installed, which may create a
|
|
problem
|
|
now that all paths go through authentication. If iceauth is not
|
|
currently installed
|
|
ksmserver will assert rendering the session useless.
|
|
|
|
This patch writes and manages the file directly removing the need for
|
|
external tools.
|
|
|
|
Co-authored-by: Fabian Vogt <fabian@ritter-vogt.de>
|
|
---
|
|
ksmserver/server.cpp | 281 ++++++++++++++++++++++---------------------
|
|
ksmserver/server.h | 2 +
|
|
2 files changed, 148 insertions(+), 135 deletions(-)
|
|
|
|
diff --git a/ksmserver/server.cpp b/ksmserver/server.cpp
|
|
index 62bb8fb74d..f88de40dba 100644
|
|
--- a/ksmserver/server.cpp
|
|
+++ b/ksmserver/server.cpp
|
|
@@ -54,6 +54,7 @@
|
|
#include <QFile>
|
|
#include <QPushButton>
|
|
#include <QRegularExpression>
|
|
+#include <QScopeGuard>
|
|
#include <QSocketNotifier>
|
|
#include <QStandardPaths>
|
|
|
|
@@ -287,37 +288,34 @@ static void fprintfhex(FILE *fp, unsigned int len, char *cp)
|
|
}
|
|
}
|
|
|
|
-/*
|
|
- * We use temporary files which contain commands to add/remove entries from
|
|
- * the .ICEauthority file.
|
|
- */
|
|
-static void write_iceauth(FILE *addfp, FILE *removefp, IceAuthDataEntry *entry)
|
|
-{
|
|
- fprintf(addfp, "add %s \"\" %s %s ", entry->protocol_name, entry->network_id, entry->auth_name);
|
|
- fprintfhex(addfp, entry->auth_data_length, entry->auth_data);
|
|
- fprintf(addfp, "\n");
|
|
-
|
|
- fprintf(removefp, "remove protoname=%s protodata=\"\" netid=%s authname=%s\n", entry->protocol_name, entry->network_id, entry->auth_name);
|
|
-}
|
|
-
|
|
#define MAGIC_COOKIE_LEN 16
|
|
|
|
-
|
|
Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry **authDataEntries)
|
|
{
|
|
- QTemporaryFile addTempFile;
|
|
- remTempFile = new QTemporaryFile;
|
|
+ char *filename = IceAuthFileName();
|
|
+ FILE *fp;
|
|
|
|
- if (!addTempFile.open() || !remTempFile->open())
|
|
+ if (IceLockAuthFile(filename, 10, 2, 600) != IceAuthLockSuccess) {
|
|
+ qWarning() << "Could not lock ICEAuthority file";
|
|
return 0;
|
|
+ }
|
|
+ auto cleanup = qScopeGuard([filename]() {
|
|
+ IceUnlockAuthFile(filename);
|
|
+ });
|
|
|
|
- if ((*authDataEntries = (IceAuthDataEntry *)malloc(count * 2 * sizeof(IceAuthDataEntry))) == nullptr)
|
|
+ if ((fp = fopen(filename, "ab")) == NULL) {
|
|
+ qWarning() << "Could not open ICEAuthority file";
|
|
return 0;
|
|
+ }
|
|
|
|
- FILE *addAuthFile = fopen(QFile::encodeName(addTempFile.fileName()).constData(), "r+");
|
|
- FILE *remAuthFile = fopen(QFile::encodeName(remTempFile->fileName()).constData(), "r+");
|
|
+ if ((*authDataEntries = (IceAuthDataEntry *)malloc(count * 2 * sizeof(IceAuthDataEntry))) == nullptr) {
|
|
+ (void)fclose(fp);
|
|
+ return 0;
|
|
+ }
|
|
|
|
for (int i = 0; i < numTransports * 2; i += 2) {
|
|
+ // ICE Auth Data
|
|
+
|
|
(*authDataEntries)[i].network_id = IceGetListenConnectionString(listenObjs[i / 2]);
|
|
(*authDataEntries)[i].protocol_name = (char *)"ICE";
|
|
(*authDataEntries)[i].auth_name = (char *)"MIT-MAGIC-COOKIE-1";
|
|
@@ -325,6 +323,23 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry *
|
|
(*authDataEntries)[i].auth_data = IceGenerateMagicCookie(MAGIC_COOKIE_LEN);
|
|
(*authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
|
|
|
|
+ // ICE Auth File
|
|
+ {
|
|
+ IceAuthFileEntry *file_entry = (IceAuthFileEntry *)malloc(sizeof(IceAuthFileEntry));
|
|
+ file_entry->protocol_name = strdup("ICE");
|
|
+ file_entry->protocol_data = NULL;
|
|
+ file_entry->protocol_data_length = 0;
|
|
+ file_entry->network_id = IceGetListenConnectionString(listenObjs[i / 2]);
|
|
+ file_entry->auth_name = strdup("MIT-MAGIC-COOKIE-1");
|
|
+ file_entry->auth_data = strdup((*authDataEntries)[i].auth_data);
|
|
+ file_entry->auth_data_length = MAGIC_COOKIE_LEN;
|
|
+ if (IceWriteAuthFileEntry(fp, file_entry) != 0) {
|
|
+ qWarning("Failed to write ice auth file entry");
|
|
+ }
|
|
+ IceFreeAuthFileEntry(file_entry);
|
|
+ }
|
|
+
|
|
+ // XSMP Auth Data
|
|
(*authDataEntries)[i + 1].network_id = IceGetListenConnectionString(listenObjs[i / 2]);
|
|
(*authDataEntries)[i + 1].protocol_name = (char *)"XSMP";
|
|
(*authDataEntries)[i + 1].auth_name = (char *)"MIT-MAGIC-COOKIE-1";
|
|
@@ -332,141 +347,127 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry *
|
|
(*authDataEntries)[i + 1].auth_data = IceGenerateMagicCookie(MAGIC_COOKIE_LEN);
|
|
(*authDataEntries)[i + 1].auth_data_length = MAGIC_COOKIE_LEN;
|
|
|
|
- write_iceauth(addAuthFile, remAuthFile, &(*authDataEntries)[i]);
|
|
- write_iceauth(addAuthFile, remAuthFile, &(*authDataEntries)[i + 1]);
|
|
+ // XSMP Auth file
|
|
+ {
|
|
+ IceAuthFileEntry *file_entry = (IceAuthFileEntry *)malloc(sizeof(IceAuthFileEntry));
|
|
+ file_entry->protocol_name = strdup("XSMP");
|
|
+ file_entry->protocol_data = NULL;
|
|
+ file_entry->protocol_data_length = 0;
|
|
+ file_entry->network_id = IceGetListenConnectionString(listenObjs[i / 2]);
|
|
+ file_entry->auth_name = strdup("MIT-MAGIC-COOKIE-1");
|
|
+ file_entry->auth_data = strdup((*authDataEntries)[i + 1].auth_data);
|
|
+ file_entry->auth_data_length = MAGIC_COOKIE_LEN;
|
|
+ if (IceWriteAuthFileEntry(fp, file_entry) != 0) {
|
|
+ qWarning("Failed to write xsmp ice auth file entry");
|
|
+ }
|
|
+ IceFreeAuthFileEntry(file_entry);
|
|
+ }
|
|
|
|
IceSetPaAuthData(2, &(*authDataEntries)[i]);
|
|
}
|
|
- fclose(addAuthFile);
|
|
- fclose(remAuthFile);
|
|
-
|
|
- QString iceAuth = QStandardPaths::findExecutable(QStringLiteral("iceauth"));
|
|
- if (iceAuth.isEmpty()) {
|
|
- qCWarning(KSMSERVER, "KSMServer: could not find iceauth");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- KProcess p;
|
|
- p << iceAuth << QStringLiteral("source") << addTempFile.fileName();
|
|
- p.execute();
|
|
|
|
return (1);
|
|
}
|
|
|
|
-/*
|
|
- * Free up authentication data.
|
|
- */
|
|
-void FreeAuthenticationData(int count, IceAuthDataEntry *authDataEntries)
|
|
-{
|
|
- /* Each transport has entries for ICE and XSMP */
|
|
- for (int i = 0; i < count * 2; i++) {
|
|
- free(authDataEntries[i].network_id);
|
|
- free(authDataEntries[i].auth_data);
|
|
- }
|
|
-
|
|
- free(authDataEntries);
|
|
-
|
|
- QString iceAuth = QStandardPaths::findExecutable(QStringLiteral("iceauth"));
|
|
- if (iceAuth.isEmpty()) {
|
|
- qCWarning(KSMSERVER, "KSMServer: could not find iceauth");
|
|
- return;
|
|
- }
|
|
+ /*
|
|
+ * Free up authentication data.
|
|
+ */
|
|
+ void FreeAuthenticationData(int count, IceAuthDataEntry *authDataEntries)
|
|
+ {
|
|
+ /* Each transport has entries for ICE and XSMP */
|
|
+ for (int i = 0; i < count * 2; i++) {
|
|
+ free(authDataEntries[i].network_id);
|
|
+ free(authDataEntries[i].auth_data);
|
|
+ }
|
|
|
|
- if (remTempFile) {
|
|
- KProcess p;
|
|
- p << iceAuth << QStringLiteral("source") << remTempFile->fileName();
|
|
- p.execute();
|
|
- }
|
|
+ free(authDataEntries);
|
|
+ }
|
|
|
|
- delete remTempFile;
|
|
- remTempFile = nullptr;
|
|
-}
|
|
+ static int Xio_ErrorHandler(Display *)
|
|
+ {
|
|
+ qCWarning(KSMSERVER, "ksmserver: Fatal IO error: client killed");
|
|
|
|
-static int Xio_ErrorHandler(Display *)
|
|
-{
|
|
- qCWarning(KSMSERVER, "ksmserver: Fatal IO error: client killed");
|
|
+ // Don't do anything that might require the X connection
|
|
+ if (the_server) {
|
|
+ KSMServer *server = the_server;
|
|
+ the_server = nullptr;
|
|
+ server->cleanUp();
|
|
+ // Don't delete server!!
|
|
+ }
|
|
|
|
- // Don't do anything that might require the X connection
|
|
- if (the_server) {
|
|
- KSMServer *server = the_server;
|
|
- the_server = nullptr;
|
|
- server->cleanUp();
|
|
- // Don't delete server!!
|
|
- }
|
|
+ exit(0); // Don't report error, it's not our fault.
|
|
+ return 0; // Bogus return value, notreached
|
|
+ }
|
|
|
|
- exit(0); // Don't report error, it's not our fault.
|
|
- return 0; // Bogus return value, notreached
|
|
-}
|
|
+ void KSMServer::setupXIOErrorHandler()
|
|
+ {
|
|
+ XSetIOErrorHandler(Xio_ErrorHandler);
|
|
+ }
|
|
|
|
-void KSMServer::setupXIOErrorHandler()
|
|
-{
|
|
- XSetIOErrorHandler(Xio_ErrorHandler);
|
|
-}
|
|
+ static int wake_up_socket = -1;
|
|
+ static void sighandler(int sig)
|
|
+ {
|
|
+ if (sig == SIGHUP) {
|
|
+ signal(SIGHUP, sighandler);
|
|
+ return;
|
|
+ }
|
|
|
|
-static int wake_up_socket = -1;
|
|
-static void sighandler(int sig)
|
|
-{
|
|
- if (sig == SIGHUP) {
|
|
- signal(SIGHUP, sighandler);
|
|
- return;
|
|
- }
|
|
+ char ch = 0;
|
|
+ (void)::write(wake_up_socket, &ch, 1);
|
|
+ }
|
|
|
|
- char ch = 0;
|
|
- (void)::write(wake_up_socket, &ch, 1);
|
|
-}
|
|
+ void KSMWatchProc(IceConn iceConn, IcePointer client_data, Bool opening, IcePointer * watch_data)
|
|
+ {
|
|
+ KSMServer *ds = (KSMServer *)client_data;
|
|
|
|
-void KSMWatchProc(IceConn iceConn, IcePointer client_data, Bool opening, IcePointer *watch_data)
|
|
-{
|
|
- KSMServer *ds = (KSMServer *)client_data;
|
|
+ if (opening) {
|
|
+ *watch_data = (IcePointer)ds->watchConnection(iceConn);
|
|
+ } else {
|
|
+ ds->removeConnection((KSMConnection *)*watch_data);
|
|
+ }
|
|
+ }
|
|
|
|
- if (opening) {
|
|
- *watch_data = (IcePointer)ds->watchConnection(iceConn);
|
|
- } else {
|
|
- ds->removeConnection((KSMConnection *)*watch_data);
|
|
- }
|
|
-}
|
|
+ static Status KSMNewClientProc(SmsConn conn, SmPointer manager_data, unsigned long *mask_ret, SmsCallbacks *cb, char **failure_reason_ret)
|
|
+ {
|
|
+ *failure_reason_ret = nullptr;
|
|
|
|
-static Status KSMNewClientProc(SmsConn conn, SmPointer manager_data, unsigned long *mask_ret, SmsCallbacks *cb, char **failure_reason_ret)
|
|
-{
|
|
- *failure_reason_ret = nullptr;
|
|
+ void *client = ((KSMServer *)manager_data)->newClient(conn);
|
|
+ if (client == NULL) {
|
|
+ const char *errstr = "Connection rejected: ksmserver is shutting down";
|
|
+ qCWarning(KSMSERVER, "%s", errstr);
|
|
|
|
- void *client = ((KSMServer *)manager_data)->newClient(conn);
|
|
- if (client == NULL) {
|
|
- const char *errstr = "Connection rejected: ksmserver is shutting down";
|
|
- qCWarning(KSMSERVER, "%s", errstr);
|
|
+ if ((*failure_reason_ret = (char *)malloc(strlen(errstr) + 1)) != NULL) {
|
|
+ strcpy(*failure_reason_ret, errstr);
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
|
|
- if ((*failure_reason_ret = (char *)malloc(strlen(errstr) + 1)) != NULL) {
|
|
- strcpy(*failure_reason_ret, errstr);
|
|
+ cb->register_client.callback = KSMRegisterClientProc;
|
|
+ cb->register_client.manager_data = client;
|
|
+ cb->interact_request.callback = KSMInteractRequestProc;
|
|
+ cb->interact_request.manager_data = client;
|
|
+ cb->interact_done.callback = KSMInteractDoneProc;
|
|
+ cb->interact_done.manager_data = client;
|
|
+ cb->save_yourself_request.callback = KSMSaveYourselfRequestProc;
|
|
+ cb->save_yourself_request.manager_data = client;
|
|
+ cb->save_yourself_phase2_request.callback = KSMSaveYourselfPhase2RequestProc;
|
|
+ cb->save_yourself_phase2_request.manager_data = client;
|
|
+ cb->save_yourself_done.callback = KSMSaveYourselfDoneProc;
|
|
+ cb->save_yourself_done.manager_data = client;
|
|
+ cb->close_connection.callback = KSMCloseConnectionProc;
|
|
+ cb->close_connection.manager_data = client;
|
|
+ cb->set_properties.callback = KSMSetPropertiesProc;
|
|
+ cb->set_properties.manager_data = client;
|
|
+ cb->delete_properties.callback = KSMDeletePropertiesProc;
|
|
+ cb->delete_properties.manager_data = client;
|
|
+ cb->get_properties.callback = KSMGetPropertiesProc;
|
|
+ cb->get_properties.manager_data = client;
|
|
+
|
|
+ *mask_ret = SmsRegisterClientProcMask | SmsInteractRequestProcMask | SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask
|
|
+ | SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask | SmsCloseConnectionProcMask | SmsSetPropertiesProcMask
|
|
+ | SmsDeletePropertiesProcMask | SmsGetPropertiesProcMask;
|
|
+ return 1;
|
|
}
|
|
- return 0;
|
|
- }
|
|
-
|
|
- cb->register_client.callback = KSMRegisterClientProc;
|
|
- cb->register_client.manager_data = client;
|
|
- cb->interact_request.callback = KSMInteractRequestProc;
|
|
- cb->interact_request.manager_data = client;
|
|
- cb->interact_done.callback = KSMInteractDoneProc;
|
|
- cb->interact_done.manager_data = client;
|
|
- cb->save_yourself_request.callback = KSMSaveYourselfRequestProc;
|
|
- cb->save_yourself_request.manager_data = client;
|
|
- cb->save_yourself_phase2_request.callback = KSMSaveYourselfPhase2RequestProc;
|
|
- cb->save_yourself_phase2_request.manager_data = client;
|
|
- cb->save_yourself_done.callback = KSMSaveYourselfDoneProc;
|
|
- cb->save_yourself_done.manager_data = client;
|
|
- cb->close_connection.callback = KSMCloseConnectionProc;
|
|
- cb->close_connection.manager_data = client;
|
|
- cb->set_properties.callback = KSMSetPropertiesProc;
|
|
- cb->set_properties.manager_data = client;
|
|
- cb->delete_properties.callback = KSMDeletePropertiesProc;
|
|
- cb->delete_properties.manager_data = client;
|
|
- cb->get_properties.callback = KSMGetPropertiesProc;
|
|
- cb->get_properties.manager_data = client;
|
|
-
|
|
- *mask_ret = SmsRegisterClientProcMask | SmsInteractRequestProcMask | SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask
|
|
- | SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask | SmsCloseConnectionProcMask | SmsSetPropertiesProcMask | SmsDeletePropertiesProcMask
|
|
- | SmsGetPropertiesProcMask;
|
|
- return 1;
|
|
-}
|
|
|
|
#ifdef HAVE__ICETRANSNOLISTEN
|
|
extern "C" int _IceTransNoListen(const char *protocol);
|
|
@@ -490,6 +491,12 @@ KSMServer::KSMServer(InitFlags flags)
|
|
QSocketNotifier *n = new QSocketNotifier(sockets[1], QSocketNotifier::Read, this);
|
|
qApp->connect(n, &QSocketNotifier::activated, &QApplication::quit);
|
|
|
|
+ const QString runtimeDirectory = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
|
|
+ iceAuthFile.setFileTemplate(runtimeDirectory + QStringLiteral("/iceauth_XXXXXX"));
|
|
+ if (!iceAuthFile.open())
|
|
+ qFatal("Failed to create ICEauthority file");
|
|
+ setenv("ICEAUTHORITY", qPrintable(iceAuthFile.fileName()), true);
|
|
+
|
|
new KSMServerInterfaceAdaptor(this);
|
|
QDBusConnection::sessionBus().registerObject(QStringLiteral("/KSMServer"), this);
|
|
the_server = this;
|
|
@@ -545,7 +552,11 @@ KSMServer::KSMServer(InitFlags flags)
|
|
fclose(f);
|
|
setenv("SESSION_MANAGER", session_manager, true);
|
|
|
|
- auto updateEnvJob = new UpdateLaunchEnvJob(QStringLiteral("SESSION_MANAGER"), QString::fromLatin1(session_manager));
|
|
+ QProcessEnvironment newEnv;
|
|
+ newEnv.insert(QStringLiteral("SESSION_MANAGER"), QString::fromLatin1(session_manager));
|
|
+ newEnv.insert(QStringLiteral("ICEAUTHORITY"), iceAuthFile.fileName());
|
|
+
|
|
+ auto updateEnvJob = new UpdateLaunchEnvJob(newEnv);
|
|
updateEnvJob->exec();
|
|
|
|
free(session_manager);
|
|
diff --git a/ksmserver/server.h b/ksmserver/server.h
|
|
index b8904ff0c3..b40629131d 100644
|
|
--- a/ksmserver/server.h
|
|
+++ b/ksmserver/server.h
|
|
@@ -25,6 +25,7 @@ extern "C" {
|
|
#include <QDBusMessage>
|
|
#include <QObject>
|
|
#include <QStringList>
|
|
+#include <QTemporaryFile>
|
|
|
|
#include <KConfigGroup>
|
|
#include <QMap>
|
|
@@ -223,5 +224,6 @@ private:
|
|
OrgKdeKWinSessionInterface *m_kwinInterface;
|
|
|
|
int sockets[2];
|
|
+ QTemporaryFile iceAuthFile;
|
|
friend bool readFromPipe(int pipe);
|
|
};
|
|
--
|
|
GitLab
|
|
|