introspect: Split out DBusSenderChecker
Restricting callers to a list of allowed senders is useful for other D-Bus services as well, so split out the existing code into a reusable class. https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3943 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1970>
This commit is contained in:
parent
d474781325
commit
2a3e297218
@ -9,6 +9,7 @@ const APP_ALLOWLIST = [
|
|||||||
const INTROSPECT_DBUS_API_VERSION = 3;
|
const INTROSPECT_DBUS_API_VERSION = 3;
|
||||||
|
|
||||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||||
|
const { DBusSenderChecker } = imports.misc.util;
|
||||||
|
|
||||||
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
|
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
|
||||||
|
|
||||||
@ -43,14 +44,7 @@ var IntrospectService = class {
|
|||||||
|
|
||||||
this._syncRunningApplications();
|
this._syncRunningApplications();
|
||||||
|
|
||||||
this._allowlistMap = new Map();
|
this._senderChecker = new DBusSenderChecker(APP_ALLOWLIST);
|
||||||
APP_ALLOWLIST.forEach(appName => {
|
|
||||||
Gio.DBus.watch_name(Gio.BusType.SESSION,
|
|
||||||
appName,
|
|
||||||
Gio.BusNameWatcherFlags.NONE,
|
|
||||||
(conn, name, owner) => this._allowlistMap.set(name, owner),
|
|
||||||
(conn, name) => this._allowlistMap.delete(name));
|
|
||||||
});
|
|
||||||
|
|
||||||
this._settings = St.Settings.get();
|
this._settings = St.Settings.get();
|
||||||
this._settings.connect('notify::enable-animations',
|
this._settings.connect('notify::enable-animations',
|
||||||
@ -67,10 +61,6 @@ var IntrospectService = class {
|
|||||||
return app.get_windows().some(w => w.transient_for == null);
|
return app.get_windows().some(w => w.transient_for == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
_isSenderAllowed(sender) {
|
|
||||||
return [...this._allowlistMap.values()].includes(sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getSandboxedAppId(app) {
|
_getSandboxedAppId(app) {
|
||||||
let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
|
let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
|
||||||
return ids.find(id => id != null);
|
return ids.find(id => id != null);
|
||||||
@ -127,21 +117,9 @@ var IntrospectService = class {
|
|||||||
type == Meta.WindowType.UTILITY;
|
type == Meta.WindowType.UTILITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkInvocation(invocation) {
|
|
||||||
if (global.context.unsafe_mode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._isSenderAllowed(invocation.get_sender()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
throw new GLib.Error(Gio.DBusError,
|
|
||||||
Gio.DBusError.ACCESS_DENIED,
|
|
||||||
'App introspection not allowed');
|
|
||||||
}
|
|
||||||
|
|
||||||
GetRunningApplicationsAsync(params, invocation) {
|
GetRunningApplicationsAsync(params, invocation) {
|
||||||
try {
|
try {
|
||||||
this._checkInvocation(invocation);
|
this._senderChecker.checkInvocation(invocation);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
invocation.return_gerror(e);
|
invocation.return_gerror(e);
|
||||||
return;
|
return;
|
||||||
@ -156,7 +134,7 @@ var IntrospectService = class {
|
|||||||
let windowsList = {};
|
let windowsList = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this._checkInvocation(invocation);
|
this._senderChecker.checkInvocation(invocation);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
invocation.return_gerror(e);
|
invocation.return_gerror(e);
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
|
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
|
||||||
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
|
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
|
||||||
ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare */
|
ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare,
|
||||||
|
DBusSenderChecker */
|
||||||
|
|
||||||
const { Clutter, Gio, GLib, Shell, St, GnomeDesktop } = imports.gi;
|
const { Clutter, Gio, GLib, Shell, St, GnomeDesktop } = imports.gi;
|
||||||
const Gettext = imports.gettext;
|
const Gettext = imports.gettext;
|
||||||
@ -477,3 +478,57 @@ function GNOMEversionCompare(version1, version2) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DBusSenderChecker = class {
|
||||||
|
/**
|
||||||
|
* @param {string[]} allowList - list of allowed well-known names
|
||||||
|
*/
|
||||||
|
constructor(allowList) {
|
||||||
|
this._allowlistMap = new Map();
|
||||||
|
|
||||||
|
this._watchList = allowList.map(name => {
|
||||||
|
return Gio.DBus.watch_name(Gio.BusType.SESSION,
|
||||||
|
name,
|
||||||
|
Gio.BusNameWatcherFlags.NONE,
|
||||||
|
(conn_, name_, owner) => this._allowlistMap.set(name, owner),
|
||||||
|
() => this._allowlistMap.delete(name));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} sender - the bus name that invoked the checked method
|
||||||
|
* @returns {bool}
|
||||||
|
*/
|
||||||
|
_isSenderAllowed(sender) {
|
||||||
|
return [...this._allowlistMap.values()].includes(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the bus name that invoked @invocation maps
|
||||||
|
* to an entry in the allow list.
|
||||||
|
*
|
||||||
|
* @throws
|
||||||
|
* @param {Gio.DBusMethodInvocation} invocation - the invocation
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
checkInvocation(invocation) {
|
||||||
|
if (global.context.unsafe_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._isSenderAllowed(invocation.get_sender()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw new GLib.Error(Gio.DBusError,
|
||||||
|
Gio.DBusError.ACCESS_DENIED,
|
||||||
|
'%s is not allowed'.format(invocation.get_method_name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
for (const id in this._watchList)
|
||||||
|
Gio.DBus.unwatch_name(id);
|
||||||
|
this._watchList = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user