You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5066 lines
183 KiB
5066 lines
183 KiB
From 1425f8f9a084e962df43dcdead04104cf1b3b83d Mon Sep 17 00:00:00 2001 |
|
From: Daniel Mack <daniel@zonque.org> |
|
Date: Fri, 12 Feb 2016 15:25:27 +0100 |
|
Subject: [PATCH] remove bus-proxyd |
|
|
|
As kdbus won't land in the anticipated way, the bus-proxy is not needed in |
|
its current form. It can be resurrected at any time thanks to the history, |
|
but for now, let's remove it from the sources. If we'll have a similar tool |
|
in the future, it will look quite differently anyway. |
|
|
|
Note that stdio-bridge is still available. It was restored from a version |
|
prior to f252ff17, and refactored to make use of the current APIs. |
|
|
|
(cherry picked from commit 798c486fbcdce3346cd862c52e1a200bb8a2cb23) |
|
Resolves: #1317518 |
|
--- |
|
.gitignore | 1 - |
|
Makefile-man.am | 2 - |
|
Makefile.am | 80 +- |
|
README | 3 - |
|
TODO | 4 - |
|
man/busctl.xml | 1 - |
|
man/systemd-bus-proxyd.xml | 109 -- |
|
man/systemd-bus-proxyd@.service.xml | 81 -- |
|
src/bus-proxyd/Makefile | 1 - |
|
src/bus-proxyd/bus-proxyd.c | 346 ------ |
|
src/bus-proxyd/bus-xml-policy.c | 1325 ---------------------- |
|
src/bus-proxyd/bus-xml-policy.h | 151 --- |
|
src/bus-proxyd/driver.c | 608 ---------- |
|
src/bus-proxyd/driver.h | 27 - |
|
src/bus-proxyd/proxy.c | 864 -------------- |
|
src/bus-proxyd/proxy.h | 53 - |
|
src/bus-proxyd/stdio-bridge.c | 263 ----- |
|
src/bus-proxyd/synthesize.c | 228 ---- |
|
src/bus-proxyd/synthesize.h | 34 - |
|
src/bus-proxyd/test-bus-xml-policy.c | 182 --- |
|
src/stdio-bridge/stdio-bridge.c | 303 +++++ |
|
src/test/test-tables.c | 3 - |
|
sysusers.d/systemd.conf.m4 | 3 - |
|
units/.gitignore | 2 - |
|
units/systemd-bus-proxyd.service.m4.in | 19 - |
|
units/systemd-bus-proxyd.socket | 12 - |
|
units/user/.gitignore | 2 - |
|
units/user/systemd-bus-proxyd.service.in | 13 - |
|
units/user/systemd-bus-proxyd.socket | 12 - |
|
29 files changed, 305 insertions(+), 4427 deletions(-) |
|
delete mode 100644 man/systemd-bus-proxyd.xml |
|
delete mode 100644 man/systemd-bus-proxyd@.service.xml |
|
delete mode 120000 src/bus-proxyd/Makefile |
|
delete mode 100644 src/bus-proxyd/bus-proxyd.c |
|
delete mode 100644 src/bus-proxyd/bus-xml-policy.c |
|
delete mode 100644 src/bus-proxyd/bus-xml-policy.h |
|
delete mode 100644 src/bus-proxyd/driver.c |
|
delete mode 100644 src/bus-proxyd/driver.h |
|
delete mode 100644 src/bus-proxyd/proxy.c |
|
delete mode 100644 src/bus-proxyd/proxy.h |
|
delete mode 100644 src/bus-proxyd/stdio-bridge.c |
|
delete mode 100644 src/bus-proxyd/synthesize.c |
|
delete mode 100644 src/bus-proxyd/synthesize.h |
|
delete mode 100644 src/bus-proxyd/test-bus-xml-policy.c |
|
create mode 100644 src/stdio-bridge/stdio-bridge.c |
|
delete mode 100644 units/systemd-bus-proxyd.service.m4.in |
|
delete mode 100644 units/systemd-bus-proxyd.socket |
|
delete mode 100644 units/user/systemd-bus-proxyd.service.in |
|
delete mode 100644 units/user/systemd-bus-proxyd.socket |
|
|
|
diff --git a/.gitignore b/.gitignore |
|
index 0360f7c6bd..5ac188bfb4 100644 |
|
--- a/.gitignore |
|
+++ b/.gitignore |
|
@@ -56,7 +56,6 @@ |
|
/systemd-backlight |
|
/systemd-binfmt |
|
/systemd-bootchart |
|
-/systemd-bus-proxyd |
|
/systemd-cat |
|
/systemd-cgls |
|
/systemd-cgroups-agent |
|
diff --git a/Makefile-man.am b/Makefile-man.am |
|
index 7ec709c8b8..734c805983 100644 |
|
--- a/Makefile-man.am |
|
+++ b/Makefile-man.am |
|
@@ -1762,8 +1762,6 @@ EXTRA_DIST += \ |
|
man/systemd-backlight@.service.xml \ |
|
man/systemd-binfmt.service.xml \ |
|
man/systemd-bootchart.xml \ |
|
- man/systemd-bus-proxyd.xml \ |
|
- man/systemd-bus-proxyd@.service.xml \ |
|
man/systemd-cat.xml \ |
|
man/systemd-cgls.xml \ |
|
man/systemd-cgtop.xml \ |
|
diff --git a/Makefile.am b/Makefile.am |
|
index b347aed7db..924b34b699 100644 |
|
--- a/Makefile.am |
|
+++ b/Makefile.am |
|
@@ -397,7 +397,6 @@ rootlibexec_PROGRAMS = \ |
|
systemd-ac-power \ |
|
systemd-sysctl \ |
|
systemd-sleep \ |
|
- systemd-bus-proxyd \ |
|
systemd-socket-proxyd \ |
|
systemd-update-done |
|
|
|
@@ -1421,7 +1420,6 @@ tests += \ |
|
test-ratelimit \ |
|
test-condition \ |
|
test-uid-range \ |
|
- test-bus-policy \ |
|
test-locale-util \ |
|
test-execute \ |
|
test-copy \ |
|
@@ -1792,14 +1790,11 @@ test_unaligned_SOURCES = \ |
|
test_tables_SOURCES = \ |
|
src/test/test-tables.c \ |
|
src/shared/test-tables.h \ |
|
- src/bus-proxyd/bus-xml-policy.c \ |
|
- src/bus-proxyd/bus-xml-policy.h \ |
|
src/journal/journald-server.c \ |
|
src/journal/journald-server.h |
|
|
|
test_tables_CPPFLAGS = \ |
|
- $(AM_CPPFLAGS) \ |
|
- -I$(top_srcdir)/src/bus-proxyd |
|
+ $(AM_CPPFLAGS) |
|
|
|
test_tables_CFLAGS = \ |
|
$(AM_CFLAGS) \ |
|
@@ -2041,14 +2036,6 @@ test_conf_files_SOURCES = \ |
|
test_conf_files_LDADD = \ |
|
libsystemd-shared.la |
|
|
|
-test_bus_policy_SOURCES = \ |
|
- src/bus-proxyd/test-bus-xml-policy.c |
|
- |
|
-test_bus_policy_LDADD = \ |
|
- libsystemd-proxy.la \ |
|
- libsystemd-internal.la \ |
|
- libsystemd-shared.la |
|
- |
|
# ------------------------------------------------------------------------------ |
|
## .PHONY so it always rebuilds it |
|
.PHONY: coverage lcov-run lcov-report coverage-sync |
|
@@ -2704,75 +2691,12 @@ systemd_run_LDADD = \ |
|
libsystemd-shared.la |
|
|
|
# ------------------------------------------------------------------------------ |
|
-noinst_LTLIBRARIES += \ |
|
- libsystemd-proxy.la |
|
- |
|
-libsystemd_proxy_la_SOURCES = \ |
|
- src/bus-proxyd/bus-xml-policy.c \ |
|
- src/bus-proxyd/bus-xml-policy.h \ |
|
- src/bus-proxyd/driver.c \ |
|
- src/bus-proxyd/driver.h \ |
|
- src/bus-proxyd/proxy.c \ |
|
- src/bus-proxyd/proxy.h \ |
|
- src/bus-proxyd/synthesize.c \ |
|
- src/bus-proxyd/synthesize.h |
|
- |
|
-libsystemd_proxy_la_CFLAGS = \ |
|
- $(AM_CFLAGS) \ |
|
- -pthread |
|
- |
|
-libsystemd_proxy_la_LIBADD = \ |
|
- libsystemd-internal.la \ |
|
- libsystemd-shared.la |
|
- |
|
-systemd_bus_proxyd_SOURCES = \ |
|
- src/bus-proxyd/bus-proxyd.c |
|
- |
|
-systemd_bus_proxyd_CFLAGS = \ |
|
- $(AM_CFLAGS) \ |
|
- -pthread |
|
- |
|
-systemd_bus_proxyd_LDADD = \ |
|
- libsystemd-proxy.la \ |
|
- libsystemd-internal.la \ |
|
- libsystemd-shared.la |
|
- |
|
systemd_stdio_bridge_SOURCES = \ |
|
- src/bus-proxyd/stdio-bridge.c |
|
+ src/stdio-bridge/stdio-bridge.c |
|
|
|
systemd_stdio_bridge_LDADD = \ |
|
- libsystemd-proxy.la \ |
|
libsystemd-internal.la \ |
|
libsystemd-shared.la |
|
- |
|
-if ENABLE_KDBUS |
|
-nodist_systemunit_DATA += \ |
|
- units/systemd-bus-proxyd.service |
|
- |
|
-dist_systemunit_DATA += \ |
|
- units/systemd-bus-proxyd.socket |
|
- |
|
-nodist_userunit_DATA += \ |
|
- units/user/systemd-bus-proxyd.service |
|
- |
|
-dist_userunit_DATA += \ |
|
- units/user/systemd-bus-proxyd.socket |
|
-endif |
|
- |
|
-EXTRA_DIST += \ |
|
- units/systemd-bus-proxyd.service.m4.in \ |
|
- units/user/systemd-bus-proxyd.service.in |
|
- |
|
-CLEANFILES += \ |
|
- units/systemd-bus-proxyd.service.m4 |
|
- |
|
-if HAVE_SMACK |
|
-bus-proxyd-set-cap-hook: |
|
- -$(SETCAP) cap_mac_admin+ei $(DESTDIR)$(rootlibexecdir)/systemd-bus-proxyd |
|
- |
|
-INSTALL_EXEC_HOOKS += bus-proxyd-set-cap-hook |
|
-endif |
|
- |
|
# ------------------------------------------------------------------------------ |
|
systemd_tty_ask_password_agent_SOURCES = \ |
|
src/tty-ask-password-agent/tty-ask-password-agent.c |
|
diff --git a/README b/README |
|
index ffc2cf9f20..bf75909f85 100644 |
|
--- a/README |
|
+++ b/README |
|
@@ -198,9 +198,6 @@ USERS AND GROUPS: |
|
Similarly, the name resolution daemon requires the |
|
"systemd-resolve" system user and group to exist. |
|
|
|
- Similarly, the kdbus dbus1 proxy daemon requires the |
|
- "systemd-bus-proxy" system user and group to exist. |
|
- |
|
NSS: |
|
systemd ships with three NSS modules: |
|
|
|
diff --git a/TODO b/TODO |
|
index 498d82c212..99473078ac 100644 |
|
--- a/TODO |
|
+++ b/TODO |
|
@@ -431,10 +431,6 @@ Features: |
|
- path escaping |
|
- update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now |
|
- test bloom filter generation indexes |
|
- - bus-proxy: when passing messages from kdbus, make sure we properly |
|
- handle the case where a large number of fds is appended that we |
|
- cannot pass into sendmsg() of the AF_UNIX sokcet (which only accepts |
|
- 253 messages) |
|
- kdbus: introduce a concept of "send-only" connections |
|
- kdbus: add counter for refused unicast messages that is passed out via the RECV ioctl. SImilar to the counter for dropped multicast messages we already have. |
|
|
|
diff --git a/man/busctl.xml b/man/busctl.xml |
|
index 0635280ead..c68fe236c1 100644 |
|
--- a/man/busctl.xml |
|
+++ b/man/busctl.xml |
|
@@ -468,7 +468,6 @@ o "/org/freedesktop/systemd1/job/42684"</programlisting> |
|
<ulink url="https://code.google.com/p/d-bus/">kdbus</ulink>, |
|
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>, |
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, |
|
- <citerefentry><refentrytitle>systemd-bus-proxyd</refentrytitle><manvolnum>8</manvolnum></citerefentry>, |
|
<citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, |
|
<citerefentry project='die-net'><refentrytitle>wireshark</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
|
</para> |
|
diff --git a/man/systemd-bus-proxyd.xml b/man/systemd-bus-proxyd.xml |
|
deleted file mode 100644 |
|
index e0efe99854..0000000000 |
|
--- a/man/systemd-bus-proxyd.xml |
|
+++ /dev/null |
|
@@ -1,109 +0,0 @@ |
|
-<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*--> |
|
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
|
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
|
- |
|
-<!-- |
|
-This file is part of systemd. |
|
- |
|
-Copyright 2013 Zbigniew Jędrzejewski-Szmek |
|
- |
|
-systemd is free software; you can redistribute it and/or modify it |
|
-under the terms of the GNU Lesser General Public License as published by |
|
-the Free Software Foundation; either version 2.1 of the License, or |
|
-(at your option) any later version. |
|
- |
|
-systemd 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 |
|
-Lesser General Public License for more details. |
|
- |
|
-You should have received a copy of the GNU Lesser General Public License |
|
-along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
---> |
|
- |
|
-<refentry id="systemd-bus-proxyd" conditional="ENABLE_KDBUS" |
|
- xmlns:xi="http://www.w3.org/2001/XInclude"> |
|
- |
|
- <refentryinfo> |
|
- <title>systemd-bus-proxyd</title> |
|
- <productname>systemd</productname> |
|
- |
|
- <authorgroup> |
|
- <author> |
|
- <contrib>Developer</contrib> |
|
- <firstname>Lennart</firstname> |
|
- <surname>Poettering</surname> |
|
- <email>lennart@poettering.net</email> |
|
- </author> |
|
- </authorgroup> |
|
- </refentryinfo> |
|
- |
|
- <refmeta> |
|
- <refentrytitle>systemd-bus-proxyd</refentrytitle> |
|
- <manvolnum>8</manvolnum> |
|
- </refmeta> |
|
- |
|
- <refnamediv> |
|
- <refname>systemd-bus-proxyd</refname> |
|
- <refpurpose>Connect STDIO or a socket to a given bus address</refpurpose> |
|
- </refnamediv> |
|
- |
|
- <refsynopsisdiv> |
|
- <cmdsynopsis> |
|
- <command>/usr/lib/systemd/systemd-bus-proxyd</command> |
|
- <arg choice="opt" rep="repeat">OPTIONS</arg> |
|
- <arg choice="opt"><replaceable>PLACEHOLDER</replaceable></arg> |
|
- </cmdsynopsis> |
|
- </refsynopsisdiv> |
|
- |
|
- <refsect1> |
|
- <title>Description</title> |
|
- |
|
- <para><command>systemd-bus-proxyd</command> will proxy D-Bus |
|
- messages to and from a bus. The will be either the system bus or |
|
- the bus specified with <option>--address</option> when that option |
|
- is given. Messages will be proxied to/from standard input and |
|
- output, or the socket received through socket activation.</para> |
|
- |
|
- <para>This program can be used to connect a program using classic |
|
- D-Bus to kdbus.</para> |
|
- </refsect1> |
|
- |
|
- <refsect1> |
|
- <title>Options and Arguments</title> |
|
- |
|
- <para>The following options are understood:</para> |
|
- |
|
- <variablelist> |
|
- <varlistentry> |
|
- <term><option>--address=<replaceable>ADDRESS</replaceable><optional>:<replaceable>ADDRESS...</replaceable></optional></option></term> |
|
- |
|
- <listitem> |
|
- <para>Connect to the bus specified by |
|
- <replaceable>ADDRESS</replaceable>. Multiple colon-separated |
|
- addresses can be specified, in which case |
|
- <command>systemd-bus-proxyd</command> will attempt to |
|
- connect to them in turn.</para> |
|
- </listitem> |
|
- </varlistentry> |
|
- |
|
- <xi:include href="standard-options.xml" xpointer="help" /> |
|
- <xi:include href="standard-options.xml" xpointer="version" /> |
|
- </variablelist> |
|
- |
|
- <para><replaceable>PLACEHOLDER</replaceable>, if given, must be a string |
|
- of <literal>x</literal> and will be used to display information about |
|
- the process that <command>systemd-bus-proxyd</command> is forwarding |
|
- messages for.</para> |
|
- </refsect1> |
|
- |
|
- <refsect1> |
|
- <title>See Also</title> |
|
- |
|
- <para> |
|
- <citerefentry project='dbus'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>, |
|
- <ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink>, |
|
- <ulink url="https://code.google.com/p/d-bus/">kdbus</ulink> |
|
- </para> |
|
- </refsect1> |
|
-</refentry> |
|
diff --git a/man/systemd-bus-proxyd@.service.xml b/man/systemd-bus-proxyd@.service.xml |
|
deleted file mode 100644 |
|
index dc4f07ff1b..0000000000 |
|
--- a/man/systemd-bus-proxyd@.service.xml |
|
+++ /dev/null |
|
@@ -1,81 +0,0 @@ |
|
-<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*--> |
|
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
|
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
|
- |
|
-<!-- |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2013 Zbigniew Jędrzejewski-Szmek |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
---> |
|
- |
|
-<refentry id="systemd-bus-proxyd@.service" conditional='ENABLE_KDBUS'> |
|
- |
|
- <refentryinfo> |
|
- <title>systemd-bus-proxyd@.service</title> |
|
- <productname>systemd</productname> |
|
- |
|
- <authorgroup> |
|
- <author> |
|
- <contrib>Developer</contrib> |
|
- <firstname>Lennart</firstname> |
|
- <surname>Poettering</surname> |
|
- <email>lennart@poettering.net</email> |
|
- </author> |
|
- </authorgroup> |
|
- </refentryinfo> |
|
- |
|
- <refmeta> |
|
- <refentrytitle>systemd-bus-proxyd@.service</refentrytitle> |
|
- <manvolnum>8</manvolnum> |
|
- </refmeta> |
|
- |
|
- <refnamediv> |
|
- <refname>systemd-bus-proxyd@.service</refname> |
|
- <refname>systemd-bus-proxyd.socket</refname> |
|
- <refpurpose>Proxy classic D-Bus clients to kdbus</refpurpose> |
|
- </refnamediv> |
|
- |
|
- <refsynopsisdiv> |
|
- <para><filename>systemd-bus-proxyd@.service</filename></para> |
|
- <para><filename>systemd-bus-proxyd.socket</filename></para> |
|
- </refsynopsisdiv> |
|
- |
|
- <refsect1> |
|
- <title>Description</title> |
|
- |
|
- <para><filename>systemd-bus-proxyd.socket</filename> will launch |
|
- <filename>systemd-bus-proxyd@.service</filename> for connections |
|
- to the classic D-Bus socket in |
|
- <filename>/var/run/dbus/system_bus_socket</filename>.</para> |
|
- |
|
- <para><filename>systemd-bus-proxyd@.service</filename> is launched |
|
- for an existing D-Bus connection and will use |
|
- <command>systemd-bus-proxyd</command> to proxy messages from this |
|
- connection to the system bus (either kdbus or classic D-Bus). |
|
- </para> |
|
- </refsect1> |
|
- |
|
- <refsect1> |
|
- <title>See Also</title> |
|
- |
|
- <para> |
|
- <citerefentry><refentrytitle>systemd-bus-proxyd</refentrytitle><manvolnum>8</manvolnum></citerefentry>, |
|
- <citerefentry project='dbus'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>, |
|
- <ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink>, |
|
- <ulink url="https://code.google.com/p/d-bus/">kdbus</ulink> |
|
- </para> |
|
- </refsect1> |
|
-</refentry> |
|
diff --git a/src/bus-proxyd/Makefile b/src/bus-proxyd/Makefile |
|
deleted file mode 120000 |
|
index d0b0e8e008..0000000000 |
|
--- a/src/bus-proxyd/Makefile |
|
+++ /dev/null |
|
@@ -1 +0,0 @@ |
|
-../Makefile |
|
\ No newline at end of file |
|
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c |
|
deleted file mode 100644 |
|
index b6550ed3cf..0000000000 |
|
--- a/src/bus-proxyd/bus-proxyd.c |
|
+++ /dev/null |
|
@@ -1,346 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2010 Lennart Poettering |
|
- Copyright 2013 Daniel Mack |
|
- Copyright 2014 Kay Sievers |
|
- Copyright 2015 David Herrmann |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <sys/socket.h> |
|
-#include <sys/un.h> |
|
-#include <sys/types.h> |
|
-#include <fcntl.h> |
|
-#include <unistd.h> |
|
-#include <string.h> |
|
-#include <errno.h> |
|
-#include <poll.h> |
|
-#include <sys/prctl.h> |
|
-#include <stddef.h> |
|
-#include <getopt.h> |
|
-#include <pthread.h> |
|
- |
|
-#include "log.h" |
|
-#include "util.h" |
|
-#include "hashmap.h" |
|
-#include "socket-util.h" |
|
-#include "sd-daemon.h" |
|
-#include "sd-bus.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-util.h" |
|
-#include "build.h" |
|
-#include "strv.h" |
|
-#include "def.h" |
|
-#include "capability.h" |
|
-#include "bus-control.h" |
|
-#include "smack-util.h" |
|
-#include "set.h" |
|
-#include "bus-xml-policy.h" |
|
-#include "driver.h" |
|
-#include "proxy.h" |
|
-#include "synthesize.h" |
|
- |
|
-static char *arg_address = NULL; |
|
-static char **arg_configuration = NULL; |
|
- |
|
-typedef struct { |
|
- int fd; |
|
- SharedPolicy *policy; |
|
- uid_t bus_uid; |
|
-} ClientContext; |
|
- |
|
-static ClientContext *client_context_free(ClientContext *c) { |
|
- if (!c) |
|
- return NULL; |
|
- |
|
- safe_close(c->fd); |
|
- free(c); |
|
- |
|
- return NULL; |
|
-} |
|
- |
|
-DEFINE_TRIVIAL_CLEANUP_FUNC(ClientContext*, client_context_free); |
|
- |
|
-static int client_context_new(ClientContext **out) { |
|
- _cleanup_(client_context_freep) ClientContext *c = NULL; |
|
- |
|
- c = new0(ClientContext, 1); |
|
- if (!c) |
|
- return -ENOMEM; |
|
- |
|
- c->fd = -1; |
|
- |
|
- *out = c; |
|
- c = NULL; |
|
- return 0; |
|
-} |
|
- |
|
-static void *run_client(void *userdata) { |
|
- _cleanup_(client_context_freep) ClientContext *c = userdata; |
|
- _cleanup_(proxy_freep) Proxy *p = NULL; |
|
- char comm[16]; |
|
- int r; |
|
- |
|
- r = proxy_new(&p, c->fd, c->fd, arg_address); |
|
- if (r < 0) |
|
- goto exit; |
|
- |
|
- c->fd = -1; |
|
- |
|
- /* set comm to "p$PIDu$UID" and suffix with '*' if truncated */ |
|
- r = snprintf(comm, sizeof(comm), "p" PID_FMT "u" UID_FMT, p->local_creds.pid, p->local_creds.uid); |
|
- if (r >= (ssize_t)sizeof(comm)) |
|
- comm[sizeof(comm) - 2] = '*'; |
|
- (void) prctl(PR_SET_NAME, comm); |
|
- |
|
- r = proxy_set_policy(p, c->policy, arg_configuration); |
|
- if (r < 0) |
|
- goto exit; |
|
- |
|
- r = proxy_hello_policy(p, c->bus_uid); |
|
- if (r < 0) |
|
- goto exit; |
|
- |
|
- r = proxy_run(p); |
|
- |
|
-exit: |
|
- return NULL; |
|
-} |
|
- |
|
-static int loop_clients(int accept_fd, uid_t bus_uid) { |
|
- _cleanup_(shared_policy_freep) SharedPolicy *sp = NULL; |
|
- pthread_attr_t attr; |
|
- int r; |
|
- |
|
- r = pthread_attr_init(&attr); |
|
- if (r < 0) { |
|
- return log_error_errno(errno, "Cannot initialize pthread attributes: %m"); |
|
- } |
|
- |
|
- r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
|
- if (r < 0) { |
|
- r = log_error_errno(errno, "Cannot mark pthread attributes as detached: %m"); |
|
- goto finish; |
|
- } |
|
- |
|
- r = shared_policy_new(&sp); |
|
- if (r < 0) |
|
- goto finish; |
|
- |
|
- for (;;) { |
|
- ClientContext *c; |
|
- pthread_t tid; |
|
- int fd; |
|
- |
|
- fd = accept4(accept_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC); |
|
- if (fd < 0) { |
|
- if (errno == EAGAIN || errno == EINTR) |
|
- continue; |
|
- |
|
- r = log_error_errno(errno, "accept4() failed: %m"); |
|
- goto finish; |
|
- } |
|
- |
|
- r = client_context_new(&c); |
|
- if (r < 0) { |
|
- log_oom(); |
|
- close(fd); |
|
- continue; |
|
- } |
|
- |
|
- c->fd = fd; |
|
- c->policy = sp; |
|
- c->bus_uid = bus_uid; |
|
- |
|
- r = pthread_create(&tid, &attr, run_client, c); |
|
- if (r < 0) { |
|
- log_error("Cannot spawn thread: %m"); |
|
- client_context_free(c); |
|
- continue; |
|
- } |
|
- } |
|
- |
|
-finish: |
|
- pthread_attr_destroy(&attr); |
|
- return r; |
|
-} |
|
- |
|
-static int help(void) { |
|
- |
|
- printf("%s [OPTIONS...]\n\n" |
|
- "DBus proxy server.\n\n" |
|
- " -h --help Show this help\n" |
|
- " --version Show package version\n" |
|
- " --configuration=PATH Configuration file or directory\n" |
|
- " --machine=MACHINE Connect to specified machine\n" |
|
- " --address=ADDRESS Connect to the bus specified by ADDRESS\n" |
|
- " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n", |
|
- program_invocation_short_name); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-static int parse_argv(int argc, char *argv[]) { |
|
- |
|
- enum { |
|
- ARG_VERSION = 0x100, |
|
- ARG_ADDRESS, |
|
- ARG_CONFIGURATION, |
|
- ARG_MACHINE, |
|
- }; |
|
- |
|
- static const struct option options[] = { |
|
- { "help", no_argument, NULL, 'h' }, |
|
- { "version", no_argument, NULL, ARG_VERSION }, |
|
- { "address", required_argument, NULL, ARG_ADDRESS }, |
|
- { "configuration", required_argument, NULL, ARG_CONFIGURATION }, |
|
- { "machine", required_argument, NULL, ARG_MACHINE }, |
|
- {}, |
|
- }; |
|
- |
|
- int c, r; |
|
- |
|
- assert(argc >= 0); |
|
- assert(argv); |
|
- |
|
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) |
|
- |
|
- switch (c) { |
|
- |
|
- case 'h': |
|
- help(); |
|
- return 0; |
|
- |
|
- case ARG_VERSION: |
|
- puts(PACKAGE_STRING); |
|
- puts(SYSTEMD_FEATURES); |
|
- return 0; |
|
- |
|
- case ARG_ADDRESS: |
|
- r = free_and_strdup(&arg_address, optarg); |
|
- if (r < 0) |
|
- return log_oom(); |
|
- break; |
|
- |
|
- case ARG_CONFIGURATION: |
|
- r = strv_extend(&arg_configuration, optarg); |
|
- if (r < 0) |
|
- return log_oom(); |
|
- break; |
|
- |
|
- case ARG_MACHINE: { |
|
- _cleanup_free_ char *e = NULL; |
|
- char *a; |
|
- |
|
- e = bus_address_escape(optarg); |
|
- if (!e) |
|
- return log_oom(); |
|
- |
|
-#ifdef ENABLE_KDBUS |
|
- a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); |
|
-#else |
|
- a = strjoin("x-machine-unix:machine=", e, NULL); |
|
-#endif |
|
- if (!a) |
|
- return log_oom(); |
|
- |
|
- free(arg_address); |
|
- arg_address = a; |
|
- |
|
- break; |
|
- } |
|
- |
|
- case '?': |
|
- return -EINVAL; |
|
- |
|
- default: |
|
- assert_not_reached("Unhandled option"); |
|
- } |
|
- |
|
- if (argc > optind) { |
|
- log_error("Too many arguments"); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!arg_address) { |
|
- arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS); |
|
- if (!arg_address) |
|
- return log_oom(); |
|
- } |
|
- |
|
- return 1; |
|
-} |
|
- |
|
-int main(int argc, char *argv[]) { |
|
- int r, accept_fd; |
|
- uid_t uid, bus_uid; |
|
- gid_t gid; |
|
- |
|
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); |
|
- log_parse_environment(); |
|
- log_open(); |
|
- |
|
- bus_uid = getuid(); |
|
- |
|
- if (geteuid() == 0) { |
|
- const char *user = "systemd-bus-proxy"; |
|
- |
|
- r = get_user_creds(&user, &uid, &gid, NULL, NULL); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Cannot resolve user name %s: %m", user); |
|
- goto finish; |
|
- } |
|
- |
|
- r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Cannot drop privileges: %m"); |
|
- goto finish; |
|
- } |
|
- } |
|
- |
|
- r = parse_argv(argc, argv); |
|
- if (r <= 0) |
|
- goto finish; |
|
- |
|
- r = sd_listen_fds(0); |
|
- if (r != 1) { |
|
- log_error("Illegal number of file descriptors passed"); |
|
- goto finish; |
|
- } |
|
- |
|
- accept_fd = SD_LISTEN_FDS_START; |
|
- |
|
- r = fd_nonblock(accept_fd, false); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Cannot mark accept-fd non-blocking: %m"); |
|
- goto finish; |
|
- } |
|
- |
|
- r = loop_clients(accept_fd, bus_uid); |
|
- |
|
-finish: |
|
- sd_notify(false, |
|
- "STOPPING=1\n" |
|
- "STATUS=Shutting down."); |
|
- |
|
- strv_free(arg_configuration); |
|
- free(arg_address); |
|
- |
|
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
|
-} |
|
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c |
|
deleted file mode 100644 |
|
index f6ac0c0093..0000000000 |
|
--- a/src/bus-proxyd/bus-xml-policy.c |
|
+++ /dev/null |
|
@@ -1,1325 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2013 Lennart Poettering |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include "xml.h" |
|
-#include "fileio.h" |
|
-#include "strv.h" |
|
-#include "set.h" |
|
-#include "conf-files.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-xml-policy.h" |
|
-#include "sd-login.h" |
|
- |
|
-static void policy_item_free(PolicyItem *i) { |
|
- assert(i); |
|
- |
|
- free(i->interface); |
|
- free(i->member); |
|
- free(i->error); |
|
- free(i->name); |
|
- free(i->path); |
|
- free(i); |
|
-} |
|
- |
|
-DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem*, policy_item_free); |
|
- |
|
-static void item_append(PolicyItem *i, PolicyItem **list) { |
|
- |
|
- PolicyItem *tail; |
|
- |
|
- LIST_FIND_TAIL(items, *list, tail); |
|
- LIST_INSERT_AFTER(items, *list, tail, i); |
|
-} |
|
- |
|
-static int file_load(Policy *p, const char *path) { |
|
- |
|
- _cleanup_free_ char *c = NULL, *policy_user = NULL, *policy_group = NULL; |
|
- _cleanup_(policy_item_freep) PolicyItem *i = NULL; |
|
- void *xml_state = NULL; |
|
- unsigned n_other = 0; |
|
- const char *q; |
|
- int r; |
|
- |
|
- enum { |
|
- STATE_OUTSIDE, |
|
- STATE_BUSCONFIG, |
|
- STATE_POLICY, |
|
- STATE_POLICY_CONTEXT, |
|
- STATE_POLICY_CONSOLE, |
|
- STATE_POLICY_USER, |
|
- STATE_POLICY_GROUP, |
|
- STATE_POLICY_OTHER_ATTRIBUTE, |
|
- STATE_ALLOW_DENY, |
|
- STATE_ALLOW_DENY_INTERFACE, |
|
- STATE_ALLOW_DENY_MEMBER, |
|
- STATE_ALLOW_DENY_ERROR, |
|
- STATE_ALLOW_DENY_PATH, |
|
- STATE_ALLOW_DENY_MESSAGE_TYPE, |
|
- STATE_ALLOW_DENY_NAME, |
|
- STATE_ALLOW_DENY_OTHER_ATTRIBUTE, |
|
- STATE_OTHER, |
|
- } state = STATE_OUTSIDE; |
|
- |
|
- enum { |
|
- POLICY_CATEGORY_NONE, |
|
- POLICY_CATEGORY_DEFAULT, |
|
- POLICY_CATEGORY_MANDATORY, |
|
- POLICY_CATEGORY_ON_CONSOLE, |
|
- POLICY_CATEGORY_NO_CONSOLE, |
|
- POLICY_CATEGORY_USER, |
|
- POLICY_CATEGORY_GROUP |
|
- } policy_category = POLICY_CATEGORY_NONE; |
|
- |
|
- unsigned line = 0; |
|
- |
|
- assert(p); |
|
- |
|
- r = read_full_file(path, &c, NULL); |
|
- if (r < 0) { |
|
- if (r == -ENOENT) |
|
- return 0; |
|
- if (r == -EISDIR) |
|
- return r; |
|
- |
|
- return log_error_errno(r, "Failed to load %s: %m", path); |
|
- } |
|
- |
|
- q = c; |
|
- for (;;) { |
|
- _cleanup_free_ char *name = NULL; |
|
- int t; |
|
- |
|
- t = xml_tokenize(&q, &name, &xml_state, &line); |
|
- if (t < 0) |
|
- return log_error_errno(t, "XML parse failure in %s: %m", path); |
|
- |
|
- switch (state) { |
|
- |
|
- case STATE_OUTSIDE: |
|
- |
|
- if (t == XML_TAG_OPEN) { |
|
- if (streq(name, "busconfig")) |
|
- state = STATE_BUSCONFIG; |
|
- else { |
|
- log_error("Unexpected tag %s at %s:%u.", name, path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- } else if (t == XML_END) |
|
- return 0; |
|
- else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { |
|
- log_error("Unexpected token (1) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_BUSCONFIG: |
|
- |
|
- if (t == XML_TAG_OPEN) { |
|
- if (streq(name, "policy")) { |
|
- state = STATE_POLICY; |
|
- policy_category = POLICY_CATEGORY_NONE; |
|
- free(policy_user); |
|
- free(policy_group); |
|
- policy_user = policy_group = NULL; |
|
- } else { |
|
- state = STATE_OTHER; |
|
- n_other = 0; |
|
- } |
|
- } else if (t == XML_TAG_CLOSE_EMPTY || |
|
- (t == XML_TAG_CLOSE && streq(name, "busconfig"))) |
|
- state = STATE_OUTSIDE; |
|
- else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { |
|
- log_error("Unexpected token (2) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_POLICY: |
|
- |
|
- if (t == XML_ATTRIBUTE_NAME) { |
|
- if (streq(name, "context")) |
|
- state = STATE_POLICY_CONTEXT; |
|
- else if (streq(name, "at_console")) |
|
- state = STATE_POLICY_CONSOLE; |
|
- else if (streq(name, "user")) |
|
- state = STATE_POLICY_USER; |
|
- else if (streq(name, "group")) |
|
- state = STATE_POLICY_GROUP; |
|
- else { |
|
- log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name, path, line); |
|
- state = STATE_POLICY_OTHER_ATTRIBUTE; |
|
- } |
|
- } else if (t == XML_TAG_CLOSE_EMPTY || |
|
- (t == XML_TAG_CLOSE && streq(name, "policy"))) |
|
- state = STATE_BUSCONFIG; |
|
- else if (t == XML_TAG_OPEN) { |
|
- PolicyItemType it; |
|
- |
|
- if (streq(name, "allow")) |
|
- it = POLICY_ITEM_ALLOW; |
|
- else if (streq(name, "deny")) |
|
- it = POLICY_ITEM_DENY; |
|
- else { |
|
- log_warning("Unknown tag %s in <policy> %s:%u.", name, path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- assert(!i); |
|
- i = new0(PolicyItem, 1); |
|
- if (!i) |
|
- return log_oom(); |
|
- |
|
- i->type = it; |
|
- state = STATE_ALLOW_DENY; |
|
- |
|
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { |
|
- log_error("Unexpected token (3) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_POLICY_CONTEXT: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- if (streq(name, "default")) { |
|
- policy_category = POLICY_CATEGORY_DEFAULT; |
|
- state = STATE_POLICY; |
|
- } else if (streq(name, "mandatory")) { |
|
- policy_category = POLICY_CATEGORY_MANDATORY; |
|
- state = STATE_POLICY; |
|
- } else { |
|
- log_error("context= parameter %s unknown for <policy> at %s:%u.", name, path, line); |
|
- return -EINVAL; |
|
- } |
|
- } else { |
|
- log_error("Unexpected token (4) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_POLICY_CONSOLE: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- if (streq(name, "true")) { |
|
- policy_category = POLICY_CATEGORY_ON_CONSOLE; |
|
- state = STATE_POLICY; |
|
- } else if (streq(name, "false")) { |
|
- policy_category = POLICY_CATEGORY_NO_CONSOLE; |
|
- state = STATE_POLICY; |
|
- } else { |
|
- log_error("at_console= parameter %s unknown for <policy> at %s:%u.", name, path, line); |
|
- return -EINVAL; |
|
- } |
|
- } else { |
|
- log_error("Unexpected token (4.1) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_POLICY_USER: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- free(policy_user); |
|
- policy_user = name; |
|
- name = NULL; |
|
- policy_category = POLICY_CATEGORY_USER; |
|
- state = STATE_POLICY; |
|
- } else { |
|
- log_error("Unexpected token (5) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_POLICY_GROUP: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- free(policy_group); |
|
- policy_group = name; |
|
- name = NULL; |
|
- policy_category = POLICY_CATEGORY_GROUP; |
|
- state = STATE_POLICY; |
|
- } else { |
|
- log_error("Unexpected token (6) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_POLICY_OTHER_ATTRIBUTE: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) |
|
- state = STATE_POLICY; |
|
- else { |
|
- log_error("Unexpected token (7) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY: |
|
- |
|
- assert(i); |
|
- |
|
- if (t == XML_ATTRIBUTE_NAME) { |
|
- PolicyItemClass ic; |
|
- |
|
- if (startswith(name, "send_")) |
|
- ic = POLICY_ITEM_SEND; |
|
- else if (startswith(name, "receive_")) |
|
- ic = POLICY_ITEM_RECV; |
|
- else if (streq(name, "own")) |
|
- ic = POLICY_ITEM_OWN; |
|
- else if (streq(name, "own_prefix")) |
|
- ic = POLICY_ITEM_OWN_PREFIX; |
|
- else if (streq(name, "user")) |
|
- ic = POLICY_ITEM_USER; |
|
- else if (streq(name, "group")) |
|
- ic = POLICY_ITEM_GROUP; |
|
- else if (streq(name, "eavesdrop")) { |
|
- log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); |
|
- state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; |
|
- break; |
|
- } else { |
|
- log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); |
|
- state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; |
|
- break; |
|
- } |
|
- |
|
- if (i->class != _POLICY_ITEM_CLASS_UNSET && ic != i->class) { |
|
- log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- i->class = ic; |
|
- |
|
- if (ic == POLICY_ITEM_SEND || ic == POLICY_ITEM_RECV) { |
|
- const char *u; |
|
- |
|
- u = strchr(name, '_'); |
|
- assert(u); |
|
- |
|
- u++; |
|
- |
|
- if (streq(u, "interface")) |
|
- state = STATE_ALLOW_DENY_INTERFACE; |
|
- else if (streq(u, "member")) |
|
- state = STATE_ALLOW_DENY_MEMBER; |
|
- else if (streq(u, "error")) |
|
- state = STATE_ALLOW_DENY_ERROR; |
|
- else if (streq(u, "path")) |
|
- state = STATE_ALLOW_DENY_PATH; |
|
- else if (streq(u, "type")) |
|
- state = STATE_ALLOW_DENY_MESSAGE_TYPE; |
|
- else if ((streq(u, "destination") && ic == POLICY_ITEM_SEND) || |
|
- (streq(u, "sender") && ic == POLICY_ITEM_RECV)) |
|
- state = STATE_ALLOW_DENY_NAME; |
|
- else { |
|
- if (streq(u, "requested_reply")) |
|
- log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); |
|
- else |
|
- log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); |
|
- state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; |
|
- break; |
|
- } |
|
- } else |
|
- state = STATE_ALLOW_DENY_NAME; |
|
- |
|
- } else if (t == XML_TAG_CLOSE_EMPTY || |
|
- (t == XML_TAG_CLOSE && streq(name, i->type == POLICY_ITEM_ALLOW ? "allow" : "deny"))) { |
|
- |
|
- /* If the tag is fully empty so far, we consider it a recv */ |
|
- if (i->class == _POLICY_ITEM_CLASS_UNSET) |
|
- i->class = POLICY_ITEM_RECV; |
|
- |
|
- if (policy_category == POLICY_CATEGORY_DEFAULT) |
|
- item_append(i, &p->default_items); |
|
- else if (policy_category == POLICY_CATEGORY_MANDATORY) |
|
- item_append(i, &p->mandatory_items); |
|
- else if (policy_category == POLICY_CATEGORY_ON_CONSOLE) |
|
- item_append(i, &p->on_console_items); |
|
- else if (policy_category == POLICY_CATEGORY_NO_CONSOLE) |
|
- item_append(i, &p->no_console_items); |
|
- else if (policy_category == POLICY_CATEGORY_USER) { |
|
- const char *u = policy_user; |
|
- |
|
- assert_cc(sizeof(uid_t) == sizeof(uint32_t)); |
|
- |
|
- r = hashmap_ensure_allocated(&p->user_items, NULL); |
|
- if (r < 0) |
|
- return log_oom(); |
|
- |
|
- if (!u) { |
|
- log_error("User policy without name"); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Failed to resolve user %s, ignoring policy: %m", u); |
|
- free(i); |
|
- } else { |
|
- PolicyItem *first; |
|
- |
|
- first = hashmap_get(p->user_items, UINT32_TO_PTR(i->uid)); |
|
- item_append(i, &first); |
|
- i->uid_valid = true; |
|
- |
|
- r = hashmap_replace(p->user_items, UINT32_TO_PTR(i->uid), first); |
|
- if (r < 0) { |
|
- LIST_REMOVE(items, first, i); |
|
- return log_oom(); |
|
- } |
|
- } |
|
- |
|
- } else if (policy_category == POLICY_CATEGORY_GROUP) { |
|
- const char *g = policy_group; |
|
- |
|
- assert_cc(sizeof(gid_t) == sizeof(uint32_t)); |
|
- |
|
- r = hashmap_ensure_allocated(&p->group_items, NULL); |
|
- if (r < 0) |
|
- return log_oom(); |
|
- |
|
- if (!g) { |
|
- log_error("Group policy without name"); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- r = get_group_creds(&g, &i->gid); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Failed to resolve group %s, ignoring policy: %m", g); |
|
- free(i); |
|
- } else { |
|
- PolicyItem *first; |
|
- |
|
- first = hashmap_get(p->group_items, UINT32_TO_PTR(i->gid)); |
|
- item_append(i, &first); |
|
- i->gid_valid = true; |
|
- |
|
- r = hashmap_replace(p->group_items, UINT32_TO_PTR(i->gid), first); |
|
- if (r < 0) { |
|
- LIST_REMOVE(items, first, i); |
|
- return log_oom(); |
|
- } |
|
- } |
|
- } |
|
- |
|
- state = STATE_POLICY; |
|
- i = NULL; |
|
- |
|
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { |
|
- log_error("Unexpected token (8) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_INTERFACE: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- assert(i); |
|
- if (i->interface) { |
|
- log_error("Duplicate interface at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!streq(name, "*")) { |
|
- i->interface = name; |
|
- name = NULL; |
|
- } |
|
- state = STATE_ALLOW_DENY; |
|
- } else { |
|
- log_error("Unexpected token (9) at %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_MEMBER: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- assert(i); |
|
- if (i->member) { |
|
- log_error("Duplicate member in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!streq(name, "*")) { |
|
- i->member = name; |
|
- name = NULL; |
|
- } |
|
- state = STATE_ALLOW_DENY; |
|
- } else { |
|
- log_error("Unexpected token (10) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_ERROR: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- assert(i); |
|
- if (i->error) { |
|
- log_error("Duplicate error in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!streq(name, "*")) { |
|
- i->error = name; |
|
- name = NULL; |
|
- } |
|
- state = STATE_ALLOW_DENY; |
|
- } else { |
|
- log_error("Unexpected token (11) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_PATH: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- assert(i); |
|
- if (i->path) { |
|
- log_error("Duplicate path in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!streq(name, "*")) { |
|
- i->path = name; |
|
- name = NULL; |
|
- } |
|
- state = STATE_ALLOW_DENY; |
|
- } else { |
|
- log_error("Unexpected token (12) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_MESSAGE_TYPE: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- assert(i); |
|
- |
|
- if (i->message_type != 0) { |
|
- log_error("Duplicate message type in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!streq(name, "*")) { |
|
- r = bus_message_type_from_string(name, &i->message_type); |
|
- if (r < 0) { |
|
- log_error("Invalid message type in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- } |
|
- |
|
- state = STATE_ALLOW_DENY; |
|
- } else { |
|
- log_error("Unexpected token (13) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_NAME: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) { |
|
- assert(i); |
|
- if (i->name) { |
|
- log_error("Duplicate name in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- switch (i->class) { |
|
- case POLICY_ITEM_USER: |
|
- if (!streq(name, "*")) { |
|
- const char *u = name; |
|
- |
|
- r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); |
|
- if (r < 0) |
|
- log_error_errno(r, "Failed to resolve user %s: %m", name); |
|
- else |
|
- i->uid_valid = true; |
|
- } |
|
- break; |
|
- case POLICY_ITEM_GROUP: |
|
- if (!streq(name, "*")) { |
|
- const char *g = name; |
|
- |
|
- r = get_group_creds(&g, &i->gid); |
|
- if (r < 0) |
|
- log_error_errno(r, "Failed to resolve group %s: %m", name); |
|
- else |
|
- i->gid_valid = true; |
|
- } |
|
- break; |
|
- |
|
- case POLICY_ITEM_SEND: |
|
- case POLICY_ITEM_RECV: |
|
- |
|
- if (streq(name, "*")) { |
|
- free(name); |
|
- name = NULL; |
|
- } |
|
- break; |
|
- |
|
- |
|
- default: |
|
- break; |
|
- } |
|
- |
|
- i->name = name; |
|
- name = NULL; |
|
- |
|
- state = STATE_ALLOW_DENY; |
|
- } else { |
|
- log_error("Unexpected token (14) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_ALLOW_DENY_OTHER_ATTRIBUTE: |
|
- |
|
- if (t == XML_ATTRIBUTE_VALUE) |
|
- state = STATE_ALLOW_DENY; |
|
- else { |
|
- log_error("Unexpected token (15) in %s:%u.", path, line); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- break; |
|
- |
|
- case STATE_OTHER: |
|
- |
|
- if (t == XML_TAG_OPEN) |
|
- n_other++; |
|
- else if (t == XML_TAG_CLOSE || t == XML_TAG_CLOSE_EMPTY) { |
|
- |
|
- if (n_other == 0) |
|
- state = STATE_BUSCONFIG; |
|
- else |
|
- n_other--; |
|
- } |
|
- |
|
- break; |
|
- } |
|
- } |
|
-} |
|
- |
|
-enum { |
|
- DENY, |
|
- ALLOW, |
|
- DUNNO, |
|
-}; |
|
- |
|
-static const char *verdict_to_string(int v) { |
|
- switch (v) { |
|
- |
|
- case DENY: |
|
- return "DENY"; |
|
- case ALLOW: |
|
- return "ALLOW"; |
|
- case DUNNO: |
|
- return "DUNNO"; |
|
- } |
|
- |
|
- return NULL; |
|
-} |
|
- |
|
-struct policy_check_filter { |
|
- PolicyItemClass class; |
|
- uid_t uid; |
|
- gid_t gid; |
|
- int message_type; |
|
- const char *name; |
|
- const char *interface; |
|
- const char *path; |
|
- const char *member; |
|
-}; |
|
- |
|
-static int is_permissive(PolicyItem *i) { |
|
- |
|
- assert(i); |
|
- |
|
- return (i->type == POLICY_ITEM_ALLOW) ? ALLOW : DENY; |
|
-} |
|
- |
|
-static int check_policy_item(PolicyItem *i, const struct policy_check_filter *filter) { |
|
- |
|
- assert(i); |
|
- assert(filter); |
|
- |
|
- switch (i->class) { |
|
- case POLICY_ITEM_SEND: |
|
- case POLICY_ITEM_RECV: |
|
- |
|
- if (i->name && !streq_ptr(i->name, filter->name)) |
|
- break; |
|
- |
|
- if ((i->message_type != 0) && (i->message_type != filter->message_type)) |
|
- break; |
|
- |
|
- if (i->path && !streq_ptr(i->path, filter->path)) |
|
- break; |
|
- |
|
- if (i->member && !streq_ptr(i->member, filter->member)) |
|
- break; |
|
- |
|
- if (i->interface && !streq_ptr(i->interface, filter->interface)) |
|
- break; |
|
- |
|
- return is_permissive(i); |
|
- |
|
- case POLICY_ITEM_OWN: |
|
- assert(filter->name); |
|
- |
|
- if (streq(i->name, "*") || streq(i->name, filter->name)) |
|
- return is_permissive(i); |
|
- break; |
|
- |
|
- case POLICY_ITEM_OWN_PREFIX: |
|
- assert(filter->name); |
|
- |
|
- if (streq(i->name, "*") || service_name_startswith(filter->name, i->name)) |
|
- return is_permissive(i); |
|
- break; |
|
- |
|
- case POLICY_ITEM_USER: |
|
- if (filter->uid != UID_INVALID) |
|
- if ((streq_ptr(i->name, "*") || (i->uid_valid && i->uid == filter->uid))) |
|
- return is_permissive(i); |
|
- break; |
|
- |
|
- case POLICY_ITEM_GROUP: |
|
- if (filter->gid != GID_INVALID) |
|
- if ((streq_ptr(i->name, "*") || (i->gid_valid && i->gid == filter->gid))) |
|
- return is_permissive(i); |
|
- break; |
|
- |
|
- case POLICY_ITEM_IGNORE: |
|
- default: |
|
- break; |
|
- } |
|
- |
|
- return DUNNO; |
|
-} |
|
- |
|
-static int check_policy_items(PolicyItem *items, const struct policy_check_filter *filter) { |
|
- |
|
- PolicyItem *i; |
|
- int verdict = DUNNO; |
|
- |
|
- assert(filter); |
|
- |
|
- /* Check all policies in a set - a broader one might be followed by a more specific one, |
|
- * and the order of rules in policy definitions matters */ |
|
- LIST_FOREACH(items, i, items) { |
|
- int v; |
|
- |
|
- if (i->class != filter->class && |
|
- !(i->class == POLICY_ITEM_OWN_PREFIX && filter->class == POLICY_ITEM_OWN)) |
|
- continue; |
|
- |
|
- v = check_policy_item(i, filter); |
|
- if (v != DUNNO) |
|
- verdict = v; |
|
- } |
|
- |
|
- return verdict; |
|
-} |
|
- |
|
-static int policy_check(Policy *p, const struct policy_check_filter *filter) { |
|
- |
|
- PolicyItem *items; |
|
- int verdict, v; |
|
- |
|
- assert(p); |
|
- assert(filter); |
|
- |
|
- assert(IN_SET(filter->class, POLICY_ITEM_SEND, POLICY_ITEM_RECV, POLICY_ITEM_OWN, POLICY_ITEM_USER, POLICY_ITEM_GROUP)); |
|
- |
|
- /* |
|
- * The policy check is implemented by the following logic: |
|
- * |
|
- * 1. Check default items |
|
- * 2. Check group items |
|
- * 3. Check user items |
|
- * 4. Check on/no_console items |
|
- * 5. Check mandatory items |
|
- * |
|
- * Later rules override earlier rules. |
|
- */ |
|
- |
|
- verdict = check_policy_items(p->default_items, filter); |
|
- |
|
- if (filter->gid != GID_INVALID) { |
|
- items = hashmap_get(p->group_items, UINT32_TO_PTR(filter->gid)); |
|
- if (items) { |
|
- v = check_policy_items(items, filter); |
|
- if (v != DUNNO) |
|
- verdict = v; |
|
- } |
|
- } |
|
- |
|
- if (filter->uid != UID_INVALID) { |
|
- items = hashmap_get(p->user_items, UINT32_TO_PTR(filter->uid)); |
|
- if (items) { |
|
- v = check_policy_items(items, filter); |
|
- if (v != DUNNO) |
|
- verdict = v; |
|
- } |
|
- } |
|
- |
|
- if (filter->uid != UID_INVALID && sd_uid_get_seats(filter->uid, -1, NULL) > 0) |
|
- v = check_policy_items(p->on_console_items, filter); |
|
- else |
|
- v = check_policy_items(p->no_console_items, filter); |
|
- if (v != DUNNO) |
|
- verdict = v; |
|
- |
|
- v = check_policy_items(p->mandatory_items, filter); |
|
- if (v != DUNNO) |
|
- verdict = v; |
|
- |
|
- return verdict; |
|
-} |
|
- |
|
-bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name) { |
|
- |
|
- struct policy_check_filter filter = { |
|
- .class = POLICY_ITEM_OWN, |
|
- .uid = uid, |
|
- .gid = gid, |
|
- .name = name, |
|
- }; |
|
- |
|
- int verdict; |
|
- |
|
- assert(p); |
|
- assert(name); |
|
- |
|
- verdict = policy_check(p, &filter); |
|
- |
|
- log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), |
|
- "Ownership permission check for uid=" UID_FMT " gid=" GID_FMT" name=%s: %s", |
|
- uid, gid, strna(name), strna(verdict_to_string(verdict))); |
|
- |
|
- return verdict == ALLOW; |
|
-} |
|
- |
|
-bool policy_check_hello(Policy *p, uid_t uid, gid_t gid) { |
|
- |
|
- struct policy_check_filter filter = { |
|
- .uid = uid, |
|
- .gid = gid, |
|
- }; |
|
- int verdict; |
|
- |
|
- assert(p); |
|
- |
|
- filter.class = POLICY_ITEM_USER; |
|
- verdict = policy_check(p, &filter); |
|
- |
|
- if (verdict != DENY) { |
|
- int v; |
|
- |
|
- filter.class = POLICY_ITEM_GROUP; |
|
- v = policy_check(p, &filter); |
|
- if (v != DUNNO) |
|
- verdict = v; |
|
- } |
|
- |
|
- log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), |
|
- "Hello permission check for uid=" UID_FMT " gid=" GID_FMT": %s", |
|
- uid, gid, strna(verdict_to_string(verdict))); |
|
- |
|
- return verdict == ALLOW; |
|
-} |
|
- |
|
-bool policy_check_one_recv(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- const char *name, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member) { |
|
- |
|
- struct policy_check_filter filter = { |
|
- .class = POLICY_ITEM_RECV, |
|
- .uid = uid, |
|
- .gid = gid, |
|
- .message_type = message_type, |
|
- .name = name, |
|
- .interface = interface, |
|
- .path = path, |
|
- .member = member, |
|
- }; |
|
- |
|
- assert(p); |
|
- |
|
- return policy_check(p, &filter) == ALLOW; |
|
-} |
|
- |
|
-bool policy_check_recv(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- Set *names, |
|
- char **namesv, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member, |
|
- bool dbus_to_kernel) { |
|
- |
|
- char *n, **nv, *last = NULL; |
|
- bool allow = false; |
|
- Iterator i; |
|
- |
|
- assert(p); |
|
- |
|
- if (set_isempty(names) && strv_isempty(namesv)) { |
|
- allow = policy_check_one_recv(p, uid, gid, message_type, NULL, path, interface, member); |
|
- } else { |
|
- SET_FOREACH(n, names, i) { |
|
- last = n; |
|
- allow = policy_check_one_recv(p, uid, gid, message_type, n, path, interface, member); |
|
- if (allow) |
|
- break; |
|
- } |
|
- if (!allow) { |
|
- STRV_FOREACH(nv, namesv) { |
|
- last = *nv; |
|
- allow = policy_check_one_recv(p, uid, gid, message_type, *nv, path, interface, member); |
|
- if (allow) |
|
- break; |
|
- } |
|
- } |
|
- } |
|
- |
|
- log_full(LOG_AUTH | (!allow ? LOG_WARNING : LOG_DEBUG), |
|
- "Receive permission check %s for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s path=%s interface=%s member=%s: %s", |
|
- dbus_to_kernel ? "dbus-1 to kernel" : "kernel to dbus-1", uid, gid, bus_message_type_to_string(message_type), strna(last), |
|
- strna(path), strna(interface), strna(member), allow ? "ALLOW" : "DENY"); |
|
- |
|
- return allow; |
|
-} |
|
- |
|
-bool policy_check_one_send(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- const char *name, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member) { |
|
- |
|
- struct policy_check_filter filter = { |
|
- .class = POLICY_ITEM_SEND, |
|
- .uid = uid, |
|
- .gid = gid, |
|
- .message_type = message_type, |
|
- .name = name, |
|
- .interface = interface, |
|
- .path = path, |
|
- .member = member, |
|
- }; |
|
- |
|
- assert(p); |
|
- |
|
- return policy_check(p, &filter) == ALLOW; |
|
-} |
|
- |
|
-bool policy_check_send(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- Set *names, |
|
- char **namesv, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member, |
|
- bool dbus_to_kernel, |
|
- char **out_used_name) { |
|
- |
|
- char *n, **nv, *last = NULL; |
|
- bool allow = false; |
|
- Iterator i; |
|
- |
|
- assert(p); |
|
- |
|
- if (set_isempty(names) && strv_isempty(namesv)) { |
|
- allow = policy_check_one_send(p, uid, gid, message_type, NULL, path, interface, member); |
|
- } else { |
|
- SET_FOREACH(n, names, i) { |
|
- last = n; |
|
- allow = policy_check_one_send(p, uid, gid, message_type, n, path, interface, member); |
|
- if (allow) |
|
- break; |
|
- } |
|
- if (!allow) { |
|
- STRV_FOREACH(nv, namesv) { |
|
- last = *nv; |
|
- allow = policy_check_one_send(p, uid, gid, message_type, *nv, path, interface, member); |
|
- if (allow) |
|
- break; |
|
- } |
|
- } |
|
- } |
|
- |
|
- if (out_used_name) |
|
- *out_used_name = last; |
|
- |
|
- log_full(LOG_AUTH | (!allow ? LOG_WARNING : LOG_DEBUG), |
|
- "Send permission check %s for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s path=%s interface=%s member=%s: %s", |
|
- dbus_to_kernel ? "dbus-1 to kernel" : "kernel to dbus-1", uid, gid, bus_message_type_to_string(message_type), strna(last), |
|
- strna(path), strna(interface), strna(member), allow ? "ALLOW" : "DENY"); |
|
- |
|
- return allow; |
|
-} |
|
- |
|
-int policy_load(Policy *p, char **files) { |
|
- char **i; |
|
- int r; |
|
- |
|
- assert(p); |
|
- |
|
- STRV_FOREACH(i, files) { |
|
- |
|
- r = file_load(p, *i); |
|
- if (r == -EISDIR) { |
|
- _cleanup_strv_free_ char **l = NULL; |
|
- char **j; |
|
- |
|
- r = conf_files_list(&l, ".conf", NULL, *i, NULL); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to get configuration file list: %m"); |
|
- |
|
- STRV_FOREACH(j, l) |
|
- file_load(p, *j); |
|
- } |
|
- |
|
- /* We ignore all errors but EISDIR, and just proceed. */ |
|
- } |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-void policy_free(Policy *p) { |
|
- PolicyItem *i, *first; |
|
- |
|
- if (!p) |
|
- return; |
|
- |
|
- while ((i = p->default_items)) { |
|
- LIST_REMOVE(items, p->default_items, i); |
|
- policy_item_free(i); |
|
- } |
|
- |
|
- while ((i = p->mandatory_items)) { |
|
- LIST_REMOVE(items, p->mandatory_items, i); |
|
- policy_item_free(i); |
|
- } |
|
- |
|
- while ((i = p->on_console_items)) { |
|
- LIST_REMOVE(items, p->on_console_items, i); |
|
- policy_item_free(i); |
|
- } |
|
- |
|
- while ((i = p->no_console_items)) { |
|
- LIST_REMOVE(items, p->no_console_items, i); |
|
- policy_item_free(i); |
|
- } |
|
- |
|
- while ((first = hashmap_steal_first(p->user_items))) { |
|
- |
|
- while ((i = first)) { |
|
- LIST_REMOVE(items, first, i); |
|
- policy_item_free(i); |
|
- } |
|
- } |
|
- |
|
- while ((first = hashmap_steal_first(p->group_items))) { |
|
- |
|
- while ((i = first)) { |
|
- LIST_REMOVE(items, first, i); |
|
- policy_item_free(i); |
|
- } |
|
- } |
|
- |
|
- hashmap_free(p->user_items); |
|
- hashmap_free(p->group_items); |
|
- |
|
- p->user_items = p->group_items = NULL; |
|
-} |
|
- |
|
-static void dump_items(PolicyItem *items, const char *prefix) { |
|
- |
|
- PolicyItem *i; |
|
- |
|
- if (!items) |
|
- return; |
|
- |
|
- if (!prefix) |
|
- prefix = ""; |
|
- |
|
- LIST_FOREACH(items, i, items) { |
|
- |
|
- printf("%sType: %s\n" |
|
- "%sClass: %s\n", |
|
- prefix, policy_item_type_to_string(i->type), |
|
- prefix, policy_item_class_to_string(i->class)); |
|
- |
|
- if (i->interface) |
|
- printf("%sInterface: %s\n", |
|
- prefix, i->interface); |
|
- |
|
- if (i->member) |
|
- printf("%sMember: %s\n", |
|
- prefix, i->member); |
|
- |
|
- if (i->error) |
|
- printf("%sError: %s\n", |
|
- prefix, i->error); |
|
- |
|
- if (i->path) |
|
- printf("%sPath: %s\n", |
|
- prefix, i->path); |
|
- |
|
- if (i->name) |
|
- printf("%sName: %s\n", |
|
- prefix, i->name); |
|
- |
|
- if (i->message_type != 0) |
|
- printf("%sMessage Type: %s\n", |
|
- prefix, bus_message_type_to_string(i->message_type)); |
|
- |
|
- if (i->uid_valid) { |
|
- _cleanup_free_ char *user; |
|
- |
|
- user = uid_to_name(i->uid); |
|
- |
|
- printf("%sUser: %s ("UID_FMT")\n", |
|
- prefix, strna(user), i->uid); |
|
- } |
|
- |
|
- if (i->gid_valid) { |
|
- _cleanup_free_ char *group; |
|
- |
|
- group = gid_to_name(i->gid); |
|
- |
|
- printf("%sGroup: %s ("GID_FMT")\n", |
|
- prefix, strna(group), i->gid); |
|
- } |
|
- printf("%s-\n", prefix); |
|
- } |
|
-} |
|
- |
|
-static void dump_hashmap_items(Hashmap *h) { |
|
- PolicyItem *i; |
|
- Iterator j; |
|
- void *k; |
|
- |
|
- HASHMAP_FOREACH_KEY(i, k, h, j) { |
|
- printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW), PTR_TO_UINT(k)); |
|
- dump_items(i, "\t\t"); |
|
- } |
|
-} |
|
- |
|
-void policy_dump(Policy *p) { |
|
- |
|
- printf("%s Default Items:\n", draw_special_char(DRAW_ARROW)); |
|
- dump_items(p->default_items, "\t"); |
|
- |
|
- printf("%s Group Items:\n", draw_special_char(DRAW_ARROW)); |
|
- dump_hashmap_items(p->group_items); |
|
- |
|
- printf("%s User Items:\n", draw_special_char(DRAW_ARROW)); |
|
- dump_hashmap_items(p->user_items); |
|
- |
|
- printf("%s On-Console Items:\n", draw_special_char(DRAW_ARROW)); |
|
- dump_items(p->on_console_items, "\t"); |
|
- |
|
- printf("%s No-Console Items:\n", draw_special_char(DRAW_ARROW)); |
|
- dump_items(p->no_console_items, "\t"); |
|
- |
|
- printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW)); |
|
- dump_items(p->mandatory_items, "\t"); |
|
- |
|
- fflush(stdout); |
|
-} |
|
- |
|
-int shared_policy_new(SharedPolicy **out) { |
|
- SharedPolicy *sp; |
|
- int r; |
|
- |
|
- sp = new0(SharedPolicy, 1); |
|
- if (!sp) |
|
- return log_oom(); |
|
- |
|
- r = pthread_mutex_init(&sp->lock, NULL); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Cannot initialize shared policy mutex: %m"); |
|
- goto exit_free; |
|
- } |
|
- |
|
- r = pthread_rwlock_init(&sp->rwlock, NULL); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Cannot initialize shared policy rwlock: %m"); |
|
- goto exit_mutex; |
|
- } |
|
- |
|
- *out = sp; |
|
- sp = NULL; |
|
- return 0; |
|
- |
|
- /* pthread lock destruction is not fail-safe... meh! */ |
|
-exit_mutex: |
|
- pthread_mutex_destroy(&sp->lock); |
|
-exit_free: |
|
- free(sp); |
|
- return r; |
|
-} |
|
- |
|
-SharedPolicy *shared_policy_free(SharedPolicy *sp) { |
|
- if (!sp) |
|
- return NULL; |
|
- |
|
- policy_free(sp->policy); |
|
- pthread_rwlock_destroy(&sp->rwlock); |
|
- pthread_mutex_destroy(&sp->lock); |
|
- strv_free(sp->configuration); |
|
- free(sp); |
|
- |
|
- return NULL; |
|
-} |
|
- |
|
-static int shared_policy_reload_unlocked(SharedPolicy *sp, char **configuration) { |
|
- Policy old, buffer = {}; |
|
- bool free_old; |
|
- int r; |
|
- |
|
- assert(sp); |
|
- |
|
- r = policy_load(&buffer, configuration); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to load policy: %m"); |
|
- |
|
- log_debug("Reloading configuration"); |
|
- /* policy_dump(&buffer); */ |
|
- |
|
- pthread_rwlock_wrlock(&sp->rwlock); |
|
- memcpy(&old, &sp->buffer, sizeof(old)); |
|
- memcpy(&sp->buffer, &buffer, sizeof(buffer)); |
|
- free_old = !!sp->policy; |
|
- sp->policy = &sp->buffer; |
|
- pthread_rwlock_unlock(&sp->rwlock); |
|
- |
|
- if (free_old) |
|
- policy_free(&old); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-int shared_policy_reload(SharedPolicy *sp) { |
|
- int r; |
|
- |
|
- assert(sp); |
|
- |
|
- pthread_mutex_lock(&sp->lock); |
|
- r = shared_policy_reload_unlocked(sp, sp->configuration); |
|
- pthread_mutex_unlock(&sp->lock); |
|
- |
|
- return r; |
|
-} |
|
- |
|
-int shared_policy_preload(SharedPolicy *sp, char **configuration) { |
|
- _cleanup_strv_free_ char **conf = NULL; |
|
- int r = 0; |
|
- |
|
- assert(sp); |
|
- |
|
- conf = strv_copy(configuration); |
|
- if (!conf) |
|
- return log_oom(); |
|
- |
|
- pthread_mutex_lock(&sp->lock); |
|
- if (!sp->policy) { |
|
- r = shared_policy_reload_unlocked(sp, conf); |
|
- if (r >= 0) { |
|
- sp->configuration = conf; |
|
- conf = NULL; |
|
- } |
|
- } |
|
- pthread_mutex_unlock(&sp->lock); |
|
- |
|
- return r; |
|
-} |
|
- |
|
-Policy *shared_policy_acquire(SharedPolicy *sp) { |
|
- assert(sp); |
|
- |
|
- pthread_rwlock_rdlock(&sp->rwlock); |
|
- if (sp->policy) |
|
- return sp->policy; |
|
- pthread_rwlock_unlock(&sp->rwlock); |
|
- |
|
- return NULL; |
|
-} |
|
- |
|
-void shared_policy_release(SharedPolicy *sp, Policy *p) { |
|
- assert(sp); |
|
- assert(!p || sp->policy == p); |
|
- |
|
- if (p) |
|
- pthread_rwlock_unlock(&sp->rwlock); |
|
-} |
|
- |
|
-static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = { |
|
- [_POLICY_ITEM_TYPE_UNSET] = "unset", |
|
- [POLICY_ITEM_ALLOW] = "allow", |
|
- [POLICY_ITEM_DENY] = "deny", |
|
-}; |
|
-DEFINE_STRING_TABLE_LOOKUP(policy_item_type, PolicyItemType); |
|
- |
|
-static const char* const policy_item_class_table[_POLICY_ITEM_CLASS_MAX] = { |
|
- [_POLICY_ITEM_CLASS_UNSET] = "unset", |
|
- [POLICY_ITEM_SEND] = "send", |
|
- [POLICY_ITEM_RECV] = "recv", |
|
- [POLICY_ITEM_OWN] = "own", |
|
- [POLICY_ITEM_OWN_PREFIX] = "own-prefix", |
|
- [POLICY_ITEM_USER] = "user", |
|
- [POLICY_ITEM_GROUP] = "group", |
|
- [POLICY_ITEM_IGNORE] = "ignore", |
|
-}; |
|
-DEFINE_STRING_TABLE_LOOKUP(policy_item_class, PolicyItemClass); |
|
diff --git a/src/bus-proxyd/bus-xml-policy.h b/src/bus-proxyd/bus-xml-policy.h |
|
deleted file mode 100644 |
|
index f2ec1bbea4..0000000000 |
|
--- a/src/bus-proxyd/bus-xml-policy.h |
|
+++ /dev/null |
|
@@ -1,151 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-#pragma once |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2013 Lennart Poettering |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <inttypes.h> |
|
-#include <pthread.h> |
|
- |
|
-#include "list.h" |
|
-#include "hashmap.h" |
|
-#include "set.h" |
|
- |
|
-typedef enum PolicyItemType { |
|
- _POLICY_ITEM_TYPE_UNSET = 0, |
|
- POLICY_ITEM_ALLOW, |
|
- POLICY_ITEM_DENY, |
|
- _POLICY_ITEM_TYPE_MAX, |
|
- _POLICY_ITEM_TYPE_INVALID = -1, |
|
-} PolicyItemType; |
|
- |
|
-typedef enum PolicyItemClass { |
|
- _POLICY_ITEM_CLASS_UNSET = 0, |
|
- POLICY_ITEM_SEND, |
|
- POLICY_ITEM_RECV, |
|
- POLICY_ITEM_OWN, |
|
- POLICY_ITEM_OWN_PREFIX, |
|
- POLICY_ITEM_USER, |
|
- POLICY_ITEM_GROUP, |
|
- POLICY_ITEM_IGNORE, |
|
- _POLICY_ITEM_CLASS_MAX, |
|
- _POLICY_ITEM_CLASS_INVALID = -1, |
|
-} PolicyItemClass; |
|
- |
|
-typedef struct PolicyItem PolicyItem; |
|
- |
|
-struct PolicyItem { |
|
- PolicyItemType type; |
|
- PolicyItemClass class; |
|
- char *interface; |
|
- char *member; |
|
- char *error; |
|
- char *path; |
|
- char *name; |
|
- uint8_t message_type; |
|
- uid_t uid; |
|
- gid_t gid; |
|
- |
|
- bool uid_valid, gid_valid; |
|
- |
|
- LIST_FIELDS(PolicyItem, items); |
|
-}; |
|
- |
|
-typedef struct Policy { |
|
- LIST_HEAD(PolicyItem, default_items); |
|
- LIST_HEAD(PolicyItem, mandatory_items); |
|
- LIST_HEAD(PolicyItem, on_console_items); |
|
- LIST_HEAD(PolicyItem, no_console_items); |
|
- Hashmap *user_items; |
|
- Hashmap *group_items; |
|
-} Policy; |
|
- |
|
-typedef struct SharedPolicy { |
|
- char **configuration; |
|
- pthread_mutex_t lock; |
|
- pthread_rwlock_t rwlock; |
|
- Policy buffer; |
|
- Policy *policy; |
|
-} SharedPolicy; |
|
- |
|
-/* policy */ |
|
- |
|
-int policy_load(Policy *p, char **files); |
|
-void policy_free(Policy *p); |
|
- |
|
-bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name); |
|
-bool policy_check_hello(Policy *p, uid_t uid, gid_t gid); |
|
-bool policy_check_one_recv(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- const char *name, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member); |
|
-bool policy_check_recv(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- Set *names, |
|
- char **namesv, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member, |
|
- bool dbus_to_kernel); |
|
-bool policy_check_one_send(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- const char *name, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member); |
|
-bool policy_check_send(Policy *p, |
|
- uid_t uid, |
|
- gid_t gid, |
|
- int message_type, |
|
- Set *names, |
|
- char **namesv, |
|
- const char *path, |
|
- const char *interface, |
|
- const char *member, |
|
- bool dbus_to_kernel, |
|
- char **out_used_name); |
|
- |
|
-void policy_dump(Policy *p); |
|
- |
|
-const char* policy_item_type_to_string(PolicyItemType t) _const_; |
|
-PolicyItemType policy_item_type_from_string(const char *s) _pure_; |
|
- |
|
-const char* policy_item_class_to_string(PolicyItemClass t) _const_; |
|
-PolicyItemClass policy_item_class_from_string(const char *s) _pure_; |
|
- |
|
-/* shared policy */ |
|
- |
|
-int shared_policy_new(SharedPolicy **out); |
|
-SharedPolicy *shared_policy_free(SharedPolicy *sp); |
|
- |
|
-int shared_policy_reload(SharedPolicy *sp); |
|
-int shared_policy_preload(SharedPolicy *sp, char **configuration); |
|
-Policy *shared_policy_acquire(SharedPolicy *sp); |
|
-void shared_policy_release(SharedPolicy *sp, Policy *p); |
|
- |
|
-DEFINE_TRIVIAL_CLEANUP_FUNC(SharedPolicy*, shared_policy_free); |
|
diff --git a/src/bus-proxyd/driver.c b/src/bus-proxyd/driver.c |
|
deleted file mode 100644 |
|
index bc2c0c86f3..0000000000 |
|
--- a/src/bus-proxyd/driver.c |
|
+++ /dev/null |
|
@@ -1,608 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2010 Lennart Poettering |
|
- Copyright 2013 Daniel Mack |
|
- Copyright 2014 Kay Sievers |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <sys/types.h> |
|
-#include <unistd.h> |
|
-#include <string.h> |
|
-#include <errno.h> |
|
-#include <stddef.h> |
|
- |
|
-#include "log.h" |
|
-#include "util.h" |
|
-#include "sd-bus.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-util.h" |
|
-#include "build.h" |
|
-#include "strv.h" |
|
-#include "def.h" |
|
-#include "capability.h" |
|
-#include "bus-control.h" |
|
-#include "set.h" |
|
-#include "driver.h" |
|
-#include "synthesize.h" |
|
- |
|
-static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; |
|
- int r; |
|
- |
|
- assert(bus); |
|
- assert(name); |
|
- assert(_creds); |
|
- |
|
- r = sd_bus_get_name_creds(bus, name, mask, &c); |
|
- if (r == -ESRCH || r == -ENXIO) |
|
- return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- if ((c->mask & mask) != mask) |
|
- return -ENOTSUP; |
|
- |
|
- *_creds = c; |
|
- c = NULL; |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) { |
|
- const char *name; |
|
- int r; |
|
- |
|
- assert(bus); |
|
- assert(m); |
|
- assert(_creds); |
|
- |
|
- r = sd_bus_message_read(m, "s", &name); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- return get_creds_by_name(bus, name, mask, _creds, error); |
|
-} |
|
- |
|
-int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) { |
|
- int r; |
|
- |
|
- assert(a); |
|
- assert(b); |
|
- assert(m); |
|
- |
|
- if (!a->is_kernel) |
|
- return 0; |
|
- |
|
- if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus")) |
|
- return 0; |
|
- |
|
- /* The "Hello()" call is is handled in process_hello() */ |
|
- |
|
- if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) { |
|
- |
|
- if (!sd_bus_message_has_signature(m, "")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- return synthetic_reply_method_return(m, "s", |
|
- "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" " |
|
- "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" |
|
- "<node>\n" |
|
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" |
|
- " <method name=\"Introspect\">\n" |
|
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " </interface>\n" |
|
- " <interface name=\"org.freedesktop.DBus\">\n" |
|
- " <method name=\"AddMatch\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"RemoveMatch\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"GetConnectionSELinuxSecurityContext\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"ay\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"GetConnectionUnixProcessID\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"GetConnectionUnixUser\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"GetId\">\n" |
|
- " <arg type=\"s\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"GetNameOwner\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"s\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"Hello\">\n" |
|
- " <arg type=\"s\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"ListActivatableNames\">\n" |
|
- " <arg type=\"as\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"ListNames\">\n" |
|
- " <arg type=\"as\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"ListQueuedOwners\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"as\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"NameHasOwner\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"b\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"ReleaseName\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"ReloadConfig\">\n" |
|
- " </method>\n" |
|
- " <method name=\"RequestName\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"StartServiceByName\">\n" |
|
- " <arg type=\"s\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"in\"/>\n" |
|
- " <arg type=\"u\" direction=\"out\"/>\n" |
|
- " </method>\n" |
|
- " <method name=\"UpdateActivationEnvironment\">\n" |
|
- " <arg type=\"a{ss}\" direction=\"in\"/>\n" |
|
- " </method>\n" |
|
- " <signal name=\"NameAcquired\">\n" |
|
- " <arg type=\"s\"/>\n" |
|
- " </signal>\n" |
|
- " <signal name=\"NameLost\">\n" |
|
- " <arg type=\"s\"/>\n" |
|
- " </signal>\n" |
|
- " <signal name=\"NameOwnerChanged\">\n" |
|
- " <arg type=\"s\"/>\n" |
|
- " <arg type=\"s\"/>\n" |
|
- " <arg type=\"s\"/>\n" |
|
- " </signal>\n" |
|
- " </interface>\n" |
|
- "</node>\n"); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) { |
|
- const char *match; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "s", &match); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_add_match(a, NULL, match, NULL, NULL); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, NULL); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) { |
|
- const char *match; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "s", &match); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = bus_remove_match_by_string(a, match, NULL, NULL); |
|
- if (r == 0) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found")); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, NULL); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, &error); |
|
- |
|
- return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label)); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, &error); |
|
- |
|
- return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = get_creds_by_message(a, m, SD_BUS_CREDS_EUID, &creds, &error); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, &error); |
|
- |
|
- return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) { |
|
- sd_id128_t server_id; |
|
- char buf[SD_ID128_STRING_MAX]; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_get_bus_id(a, &server_id); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf)); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) { |
|
- const char *name; |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "s", &name); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- if (streq(name, "org.freedesktop.DBus")) |
|
- return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus"); |
|
- |
|
- r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, &error); |
|
- |
|
- return synthetic_reply_method_return(m, "s", creds->unique_name); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) { |
|
- _cleanup_strv_free_ char **names = NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_list_names(a, NULL, &names); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- /* Let's sort the names list to make it stable */ |
|
- strv_sort(names); |
|
- |
|
- return synthetic_reply_method_return_strv(m, names); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) { |
|
- _cleanup_strv_free_ char **names = NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_list_names(a, &names, NULL); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = strv_extend(&names, "org.freedesktop.DBus"); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- /* Let's sort the names list to make it stable */ |
|
- strv_sort(names); |
|
- |
|
- return synthetic_reply_method_return_strv(m, names); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) { |
|
- struct kdbus_cmd_list cmd = { |
|
- .flags = KDBUS_LIST_QUEUED, |
|
- .size = sizeof(cmd), |
|
- }; |
|
- struct kdbus_info *name_list, *name; |
|
- _cleanup_strv_free_ char **owners = NULL; |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- char *arg0; |
|
- int err = 0; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "s", &arg0); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_get_name_creds(a, arg0, 0, NULL); |
|
- if (r == -ESRCH || r == -ENXIO) { |
|
- sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0); |
|
- return synthetic_reply_method_errno(m, r, &error); |
|
- } |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, -errno, NULL); |
|
- |
|
- name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset); |
|
- |
|
- KDBUS_FOREACH(name, name_list, cmd.list_size) { |
|
- const char *entry_name = NULL; |
|
- struct kdbus_item *item; |
|
- char *n; |
|
- |
|
- KDBUS_ITEM_FOREACH(item, name, items) |
|
- if (item->type == KDBUS_ITEM_OWNED_NAME) |
|
- entry_name = item->name.name; |
|
- |
|
- if (!streq_ptr(entry_name, arg0)) |
|
- continue; |
|
- |
|
- if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) { |
|
- err = -ENOMEM; |
|
- break; |
|
- } |
|
- |
|
- r = strv_consume(&owners, n); |
|
- if (r < 0) { |
|
- err = r; |
|
- break; |
|
- } |
|
- } |
|
- |
|
- r = bus_kernel_cmd_free(a, cmd.offset); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- if (err < 0) |
|
- return synthetic_reply_method_errno(m, err, NULL); |
|
- |
|
- return synthetic_reply_method_return_strv(m, owners); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) { |
|
- const char *name; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "s", &name); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- if (streq(name, "org.freedesktop.DBus")) |
|
- return synthetic_reply_method_return(m, "b", true); |
|
- |
|
- r = sd_bus_get_name_creds(a, name, 0, NULL); |
|
- if (r < 0 && r != -ESRCH && r != -ENXIO) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, "b", r >= 0); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) { |
|
- const char *name; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "s")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "s", &name); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_release_name(a, name); |
|
- if (r < 0) { |
|
- if (r == -ESRCH) |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT); |
|
- if (r == -EADDRINUSE) |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER); |
|
- |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- } |
|
- |
|
- set_remove(owned_names, (char*) name); |
|
- |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) { |
|
- if (!sd_bus_message_has_signature(m, "")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = shared_policy_reload(sp); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, NULL); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) { |
|
- const char *name; |
|
- uint32_t flags, param; |
|
- bool in_queue; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "su")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "su", &name, &flags); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- if (sp) { |
|
- Policy *policy; |
|
- bool denied; |
|
- |
|
- policy = shared_policy_acquire(sp); |
|
- denied = !policy_check_own(policy, ucred->uid, ucred->gid, name); |
|
- shared_policy_release(sp, policy); |
|
- if (denied) |
|
- return synthetic_reply_method_errno(m, -EPERM, NULL); |
|
- } |
|
- |
|
- if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0) |
|
- return synthetic_reply_method_errno(m, -EINVAL, NULL); |
|
- |
|
- param = 0; |
|
- if (flags & BUS_NAME_ALLOW_REPLACEMENT) |
|
- param |= SD_BUS_NAME_ALLOW_REPLACEMENT; |
|
- if (flags & BUS_NAME_REPLACE_EXISTING) |
|
- param |= SD_BUS_NAME_REPLACE_EXISTING; |
|
- if (!(flags & BUS_NAME_DO_NOT_QUEUE)) |
|
- param |= SD_BUS_NAME_QUEUE; |
|
- |
|
- r = set_put_strdup(owned_names, name); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_request_name(a, name, param); |
|
- if (r < 0) { |
|
- if (r == -EALREADY) |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER); |
|
- |
|
- set_remove(owned_names, (char*) name); |
|
- |
|
- if (r == -EEXIST) |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS); |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- } |
|
- |
|
- in_queue = (r == 0); |
|
- |
|
- if (in_queue) |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE); |
|
- |
|
- return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *msg = NULL; |
|
- const char *name; |
|
- uint32_t flags; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "su")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_read(m, "su", &name, &flags); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- if (flags != 0) |
|
- return synthetic_reply_method_errno(m, -EINVAL, NULL); |
|
- |
|
- r = sd_bus_get_name_creds(a, name, 0, NULL); |
|
- if (r >= 0 || streq(name, "org.freedesktop.DBus")) |
|
- return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING); |
|
- if (r != -ESRCH) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_message_new_method_call( |
|
- a, |
|
- &msg, |
|
- name, |
|
- "/", |
|
- "org.freedesktop.DBus.Peer", |
|
- "Ping"); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_send(a, msg, NULL); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS); |
|
- |
|
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *msg = NULL; |
|
- _cleanup_strv_free_ char **args = NULL; |
|
- |
|
- if (!sd_bus_message_has_signature(m, "a{ss}")) |
|
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); |
|
- |
|
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}"); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) { |
|
- _cleanup_free_ char *s = NULL; |
|
- const char *key; |
|
- const char *value; |
|
- |
|
- r = sd_bus_message_read(m, "ss", &key, &value); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- s = strjoin(key, "=", value, NULL); |
|
- if (!s) |
|
- return synthetic_reply_method_errno(m, -ENOMEM, NULL); |
|
- |
|
- r = strv_extend(&args, s); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_message_exit_container(m); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- } |
|
- |
|
- r = sd_bus_message_exit_container(m); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- if (!args) |
|
- return synthetic_reply_method_errno(m, -EINVAL, NULL); |
|
- |
|
- r = sd_bus_message_new_method_call( |
|
- a, |
|
- &msg, |
|
- "org.freedesktop.systemd1", |
|
- "/org/freedesktop/systemd1", |
|
- "org.freedesktop.systemd1.Manager", |
|
- "SetEnvironment"); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_message_append_strv(msg, args); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- r = sd_bus_call(a, msg, 0, NULL, NULL); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(m, r, NULL); |
|
- |
|
- return synthetic_reply_method_return(m, NULL); |
|
- |
|
- } else { |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- |
|
- r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member); |
|
- |
|
- return synthetic_reply_method_errno(m, r, &error); |
|
- } |
|
-} |
|
diff --git a/src/bus-proxyd/driver.h b/src/bus-proxyd/driver.h |
|
deleted file mode 100644 |
|
index b8cedf5ce5..0000000000 |
|
--- a/src/bus-proxyd/driver.h |
|
+++ /dev/null |
|
@@ -1,27 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-#pragma once |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2014 Lennart Poettering |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include "sd-bus.h" |
|
-#include "bus-xml-policy.h" |
|
- |
|
-int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names); |
|
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c |
|
deleted file mode 100644 |
|
index e13cf5e2ea..0000000000 |
|
--- a/src/bus-proxyd/proxy.c |
|
+++ /dev/null |
|
@@ -1,864 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2010 Lennart Poettering |
|
- Copyright 2013 Daniel Mack |
|
- Copyright 2014 Kay Sievers |
|
- Copyright 2014 David Herrmann |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <sys/socket.h> |
|
-#include <sys/un.h> |
|
-#include <sys/types.h> |
|
-#include <fcntl.h> |
|
-#include <unistd.h> |
|
-#include <string.h> |
|
-#include <errno.h> |
|
-#include <poll.h> |
|
-#include <stddef.h> |
|
-#include <getopt.h> |
|
- |
|
-#include "log.h" |
|
-#include "util.h" |
|
-#include "socket-util.h" |
|
-#include "sd-daemon.h" |
|
-#include "sd-bus.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-util.h" |
|
-#include "build.h" |
|
-#include "strv.h" |
|
-#include "def.h" |
|
-#include "capability.h" |
|
-#include "bus-control.h" |
|
-#include "smack-util.h" |
|
-#include "set.h" |
|
-#include "bus-xml-policy.h" |
|
-#include "driver.h" |
|
-#include "proxy.h" |
|
-#include "synthesize.h" |
|
- |
|
-static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) { |
|
- _cleanup_bus_close_unref_ sd_bus *b = NULL; |
|
- int r; |
|
- |
|
- r = sd_bus_new(&b); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to allocate bus: %m"); |
|
- |
|
- r = sd_bus_set_description(b, "sd-proxy"); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set bus name: %m"); |
|
- |
|
- r = sd_bus_set_address(b, destination); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set address to connect to: %m"); |
|
- |
|
- r = sd_bus_negotiate_fds(b, negotiate_fds); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set FD negotiation: %m"); |
|
- |
|
- r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set credential negotiation: %m"); |
|
- |
|
- if (p->local_creds.pid > 0) { |
|
- b->fake_pids.pid = p->local_creds.pid; |
|
- b->fake_pids_valid = true; |
|
- |
|
- b->fake_creds.uid = UID_INVALID; |
|
- b->fake_creds.euid = p->local_creds.uid; |
|
- b->fake_creds.suid = UID_INVALID; |
|
- b->fake_creds.fsuid = UID_INVALID; |
|
- b->fake_creds.gid = GID_INVALID; |
|
- b->fake_creds.egid = p->local_creds.gid; |
|
- b->fake_creds.sgid = GID_INVALID; |
|
- b->fake_creds.fsgid = GID_INVALID; |
|
- b->fake_creds_valid = true; |
|
- } |
|
- |
|
- if (local_sec) { |
|
- b->fake_label = strdup(local_sec); |
|
- if (!b->fake_label) |
|
- return log_oom(); |
|
- } |
|
- |
|
- b->manual_peer_interface = true; |
|
- |
|
- r = sd_bus_start(b); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to start bus client: %m"); |
|
- |
|
- p->destination_bus = b; |
|
- b = NULL; |
|
- return 0; |
|
-} |
|
- |
|
-static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) { |
|
- _cleanup_bus_close_unref_ sd_bus *b = NULL; |
|
- sd_id128_t server_id; |
|
- int r; |
|
- |
|
- r = sd_bus_new(&b); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to allocate bus: %m"); |
|
- |
|
- r = sd_bus_set_fd(b, in_fd, out_fd); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set fds: %m"); |
|
- |
|
- r = sd_bus_get_bus_id(p->destination_bus, &server_id); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to get server ID: %m"); |
|
- |
|
- r = sd_bus_set_server(b, 1, server_id); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set server mode: %m"); |
|
- |
|
- r = sd_bus_negotiate_fds(b, negotiate_fds); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set FD negotiation: %m"); |
|
- |
|
- r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set credential negotiation: %m"); |
|
- |
|
- r = sd_bus_set_anonymous(b, true); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to set anonymous authentication: %m"); |
|
- |
|
- b->manual_peer_interface = true; |
|
- |
|
- r = sd_bus_start(b); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to start bus client: %m"); |
|
- |
|
- p->local_bus = b; |
|
- b = NULL; |
|
- return 0; |
|
-} |
|
- |
|
-static int proxy_prepare_matches(Proxy *p) { |
|
- _cleanup_free_ char *match = NULL; |
|
- const char *unique; |
|
- int r; |
|
- |
|
- if (!p->destination_bus->is_kernel) |
|
- return 0; |
|
- |
|
- r = sd_bus_get_unique_name(p->destination_bus, &unique); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to get unique name: %m"); |
|
- |
|
- match = strjoin("type='signal'," |
|
- "sender='org.freedesktop.DBus'," |
|
- "path='/org/freedesktop/DBus'," |
|
- "interface='org.freedesktop.DBus'," |
|
- "member='NameOwnerChanged'," |
|
- "arg1='", |
|
- unique, |
|
- "'", |
|
- NULL); |
|
- if (!match) |
|
- return log_oom(); |
|
- |
|
- r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to add match for NameLost: %m"); |
|
- |
|
- free(match); |
|
- match = strjoin("type='signal'," |
|
- "sender='org.freedesktop.DBus'," |
|
- "path='/org/freedesktop/DBus'," |
|
- "interface='org.freedesktop.DBus'," |
|
- "member='NameOwnerChanged'," |
|
- "arg2='", |
|
- unique, |
|
- "'", |
|
- NULL); |
|
- if (!match) |
|
- return log_oom(); |
|
- |
|
- r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to add match for NameAcquired: %m"); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) { |
|
- _cleanup_(proxy_freep) Proxy *p = NULL; |
|
- _cleanup_free_ char *local_sec = NULL; |
|
- bool is_unix; |
|
- int r; |
|
- |
|
- p = new0(Proxy, 1); |
|
- if (!p) |
|
- return log_oom(); |
|
- |
|
- p->local_in = in_fd; |
|
- p->local_out = out_fd; |
|
- |
|
- p->owned_names = set_new(&string_hash_ops); |
|
- if (!p->owned_names) |
|
- return log_oom(); |
|
- |
|
- is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && |
|
- sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0; |
|
- |
|
- if (is_unix) { |
|
- (void) getpeercred(in_fd, &p->local_creds); |
|
- (void) getpeersec(in_fd, &local_sec); |
|
- } |
|
- |
|
- r = proxy_create_destination(p, destination, local_sec, is_unix); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = proxy_create_local(p, in_fd, out_fd, is_unix); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = proxy_prepare_matches(p); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- *out = p; |
|
- p = NULL; |
|
- return 0; |
|
-} |
|
- |
|
-Proxy *proxy_free(Proxy *p) { |
|
- if (!p) |
|
- return NULL; |
|
- |
|
- sd_bus_close_unrefp(&p->local_bus); |
|
- sd_bus_close_unrefp(&p->destination_bus); |
|
- set_free_free(p->owned_names); |
|
- free(p); |
|
- |
|
- return NULL; |
|
-} |
|
- |
|
-int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) { |
|
- _cleanup_strv_free_ char **strv = NULL; |
|
- Policy *policy; |
|
- int r; |
|
- |
|
- assert(p); |
|
- assert(sp); |
|
- |
|
- /* no need to load legacy policy if destination is not kdbus */ |
|
- if (!p->destination_bus->is_kernel) |
|
- return 0; |
|
- |
|
- p->policy = sp; |
|
- |
|
- policy = shared_policy_acquire(sp); |
|
- if (policy) { |
|
- /* policy already pre-loaded */ |
|
- shared_policy_release(sp, policy); |
|
- return 0; |
|
- } |
|
- |
|
- if (!configuration) { |
|
- const char *scope; |
|
- |
|
- r = sd_bus_get_scope(p->destination_bus, &scope); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Couldn't determine bus scope: %m"); |
|
- |
|
- if (streq(scope, "system")) |
|
- strv = strv_new("/etc/dbus-1/system.conf", |
|
- "/etc/dbus-1/system.d/", |
|
- "/etc/dbus-1/system-local.conf", |
|
- NULL); |
|
- else if (streq(scope, "user")) |
|
- strv = strv_new("/etc/dbus-1/session.conf", |
|
- "/etc/dbus-1/session.d/", |
|
- "/etc/dbus-1/session-local.conf", |
|
- NULL); |
|
- else |
|
- return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope); |
|
- |
|
- if (!strv) |
|
- return log_oom(); |
|
- |
|
- configuration = strv; |
|
- } |
|
- |
|
- return shared_policy_preload(sp, configuration); |
|
-} |
|
- |
|
-int proxy_hello_policy(Proxy *p, uid_t original_uid) { |
|
- Policy *policy; |
|
- int r = 0; |
|
- |
|
- assert(p); |
|
- |
|
- if (!p->policy) |
|
- return 0; |
|
- |
|
- policy = shared_policy_acquire(p->policy); |
|
- |
|
- if (p->local_creds.uid == original_uid) |
|
- log_debug("Permitting access, since bus owner matches bus client."); |
|
- else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid)) |
|
- log_debug("Permitting access due to XML policy."); |
|
- else |
|
- r = log_error_errno(EPERM, "Policy denied connection."); |
|
- |
|
- shared_policy_release(p->policy, policy); |
|
- |
|
- return r; |
|
-} |
|
- |
|
-static int proxy_wait(Proxy *p) { |
|
- uint64_t timeout_destination, timeout_local, t; |
|
- int events_destination, events_local, fd; |
|
- struct timespec _ts, *ts; |
|
- struct pollfd *pollfd; |
|
- int r; |
|
- |
|
- assert(p); |
|
- |
|
- fd = sd_bus_get_fd(p->destination_bus); |
|
- if (fd < 0) |
|
- return log_error_errno(fd, "Failed to get fd: %m"); |
|
- |
|
- events_destination = sd_bus_get_events(p->destination_bus); |
|
- if (events_destination < 0) |
|
- return log_error_errno(events_destination, "Failed to get events mask: %m"); |
|
- |
|
- r = sd_bus_get_timeout(p->destination_bus, &timeout_destination); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to get timeout: %m"); |
|
- |
|
- events_local = sd_bus_get_events(p->local_bus); |
|
- if (events_local < 0) |
|
- return log_error_errno(events_local, "Failed to get events mask: %m"); |
|
- |
|
- r = sd_bus_get_timeout(p->local_bus, &timeout_local); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to get timeout: %m"); |
|
- |
|
- t = timeout_destination; |
|
- if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination)) |
|
- t = timeout_local; |
|
- |
|
- if (t == (uint64_t) -1) |
|
- ts = NULL; |
|
- else { |
|
- usec_t nw; |
|
- |
|
- nw = now(CLOCK_MONOTONIC); |
|
- if (t > nw) |
|
- t -= nw; |
|
- else |
|
- t = 0; |
|
- |
|
- ts = timespec_store(&_ts, t); |
|
- } |
|
- |
|
- pollfd = (struct pollfd[3]) { |
|
- { .fd = fd, .events = events_destination, }, |
|
- { .fd = p->local_in, .events = events_local & POLLIN, }, |
|
- { .fd = p->local_out, .events = events_local & POLLOUT, }, |
|
- }; |
|
- |
|
- r = ppoll(pollfd, 3, ts, NULL); |
|
- if (r < 0) |
|
- return log_error_errno(errno, "ppoll() failed: %m"); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-static int handle_policy_error(sd_bus_message *m, int r) { |
|
- if (r == -ESRCH || r == -ENXIO) |
|
- return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination); |
|
- |
|
- return r; |
|
-} |
|
- |
|
-static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) { |
|
- int r; |
|
- |
|
- assert(from); |
|
- assert(to); |
|
- assert(m); |
|
- |
|
- if (!policy) |
|
- return 0; |
|
- |
|
- /* |
|
- * dbus-1 distinguishes expected and non-expected replies by tracking |
|
- * method-calls and timeouts. By default, DENY rules are *NEVER* applied |
|
- * on expected replies, unless explicitly specified. But we dont track |
|
- * method-calls, thus, we cannot know whether a reply is expected. |
|
- * Fortunately, the kdbus forbids non-expected replies, so we can safely |
|
- * ignore any policy on those and let the kernel deal with it. |
|
- * |
|
- * TODO: To be correct, we should only ignore policy-tags that are |
|
- * applied on non-expected replies. However, so far we don't parse those |
|
- * tags so we let everything pass. I haven't seen a DENY policy tag on |
|
- * expected-replies, ever, so don't bother.. |
|
- */ |
|
- if (m->reply_cookie > 0) |
|
- return 0; |
|
- |
|
- if (from->is_kernel) { |
|
- uid_t sender_uid = UID_INVALID; |
|
- gid_t sender_gid = GID_INVALID; |
|
- char **sender_names = NULL; |
|
- |
|
- /* Driver messages are always OK */ |
|
- if (streq_ptr(m->sender, "org.freedesktop.DBus")) |
|
- return 0; |
|
- |
|
- /* The message came from the kernel, and is sent to our legacy client. */ |
|
- (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names); |
|
- |
|
- (void) sd_bus_creds_get_euid(&m->creds, &sender_uid); |
|
- (void) sd_bus_creds_get_egid(&m->creds, &sender_gid); |
|
- |
|
- if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL; |
|
- |
|
- /* If the message came from another legacy |
|
- * client, then the message creds will be |
|
- * missing, simply because on legacy clients |
|
- * per-message creds were unknown. In this |
|
- * case, query the creds of the peer |
|
- * instead. */ |
|
- |
|
- r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds); |
|
- if (r < 0) |
|
- return handle_policy_error(m, r); |
|
- |
|
- (void) sd_bus_creds_get_euid(sender_creds, &sender_uid); |
|
- (void) sd_bus_creds_get_egid(sender_creds, &sender_gid); |
|
- } |
|
- |
|
- /* First check whether the sender can send the message to our name */ |
|
- if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) && |
|
- policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false)) |
|
- return 0; |
|
- |
|
- /* Return an error back to the caller */ |
|
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) |
|
- return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy."); |
|
- |
|
- /* Return 1, indicating that the message shall not be processed any further */ |
|
- return 1; |
|
- } |
|
- |
|
- if (to->is_kernel) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL; |
|
- uid_t destination_uid = UID_INVALID; |
|
- gid_t destination_gid = GID_INVALID; |
|
- const char *destination_unique = NULL; |
|
- char **destination_names = NULL; |
|
- char *n; |
|
- |
|
- /* Driver messages are always OK */ |
|
- if (streq_ptr(m->destination, "org.freedesktop.DBus")) |
|
- return 0; |
|
- |
|
- /* The message came from the legacy client, and is sent to kdbus. */ |
|
- if (m->destination) { |
|
- r = bus_get_name_creds_kdbus(to, m->destination, |
|
- SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME| |
|
- SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID, |
|
- true, &destination_creds); |
|
- if (r < 0) |
|
- return handle_policy_error(m, r); |
|
- |
|
- r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique); |
|
- if (r < 0) |
|
- return handle_policy_error(m, r); |
|
- |
|
- (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names); |
|
- |
|
- (void) sd_bus_creds_get_euid(destination_creds, &destination_uid); |
|
- (void) sd_bus_creds_get_egid(destination_creds, &destination_gid); |
|
- } |
|
- |
|
- /* First check if we (the sender) can send to this name */ |
|
- if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) { |
|
- if (n) { |
|
- /* If we made a receiver decision, then remember which |
|
- * name's policy we used, and to which unique ID it |
|
- * mapped when we made the decision. Then, let's pass |
|
- * this to the kernel when sending the message, so that |
|
- * it refuses the operation should the name and unique |
|
- * ID not map to each other anymore. */ |
|
- |
|
- r = free_and_strdup(&m->destination_ptr, n); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id); |
|
- if (r < 0) |
|
- return r; |
|
- } |
|
- |
|
- if (sd_bus_message_is_signal(m, NULL, NULL)) { |
|
- /* If we forward a signal from dbus-1 to kdbus, |
|
- * we have no idea who the recipient is. |
|
- * Therefore, we cannot apply any dbus-1 |
|
- * receiver policies that match on receiver |
|
- * credentials. We know sd-bus always sets |
|
- * KDBUS_MSG_SIGNAL, so the kernel applies |
|
- * receiver policies to the message. Therefore, |
|
- * skip policy checks in this case. */ |
|
- return 0; |
|
- } else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) { |
|
- return 0; |
|
- } |
|
- } |
|
- |
|
- /* Return an error back to the caller */ |
|
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) |
|
- return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy."); |
|
- |
|
- /* Return 1, indicating that the message shall not be processed any further */ |
|
- return 1; |
|
- } |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) { |
|
- Policy *policy; |
|
- int r; |
|
- |
|
- assert(sp); |
|
- |
|
- policy = shared_policy_acquire(sp); |
|
- r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names); |
|
- shared_policy_release(sp, policy); |
|
- |
|
- return r; |
|
-} |
|
- |
|
-static int process_hello(Proxy *p, sd_bus_message *m) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *n = NULL; |
|
- bool is_hello; |
|
- int r; |
|
- |
|
- assert(p); |
|
- assert(m); |
|
- |
|
- /* As reaction to hello we need to respond with two messages: |
|
- * the callback reply and the NameAcquired for the unique |
|
- * name, since hello is otherwise obsolete on kdbus. */ |
|
- |
|
- is_hello = |
|
- sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") && |
|
- streq_ptr(m->destination, "org.freedesktop.DBus"); |
|
- |
|
- if (!is_hello) { |
|
- if (p->got_hello) |
|
- return 0; |
|
- |
|
- return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member); |
|
- } |
|
- |
|
- if (p->got_hello) |
|
- return log_error_errno(EIO, "Got duplicate hello, aborting."); |
|
- |
|
- p->got_hello = true; |
|
- |
|
- if (!p->destination_bus->is_kernel) |
|
- return 0; |
|
- |
|
- r = sd_bus_message_new_method_return(m, &n); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to generate HELLO reply: %m"); |
|
- |
|
- r = sd_bus_message_append(n, "s", p->destination_bus->unique_name); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to append unique name to HELLO reply: %m"); |
|
- |
|
- r = bus_message_append_sender(n, "org.freedesktop.DBus"); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to append sender to HELLO reply: %m"); |
|
- |
|
- r = bus_seal_synthetic_message(p->local_bus, n); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to seal HELLO reply: %m"); |
|
- |
|
- r = sd_bus_send(p->local_bus, n, NULL); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to send HELLO reply: %m"); |
|
- |
|
- n = sd_bus_message_unref(n); |
|
- r = sd_bus_message_new_signal( |
|
- p->local_bus, |
|
- &n, |
|
- "/org/freedesktop/DBus", |
|
- "org.freedesktop.DBus", |
|
- "NameAcquired"); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m"); |
|
- |
|
- r = sd_bus_message_append(n, "s", p->destination_bus->unique_name); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m"); |
|
- |
|
- r = bus_message_append_sender(n, "org.freedesktop.DBus"); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to append sender to NameAcquired message: %m"); |
|
- |
|
- r = bus_seal_synthetic_message(p->local_bus, n); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to seal NameAcquired message: %m"); |
|
- |
|
- r = sd_bus_send(p->local_bus, n, NULL); |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to send NameAcquired message: %m"); |
|
- |
|
- return 1; |
|
-} |
|
- |
|
-static int patch_sender(sd_bus *a, sd_bus_message *m) { |
|
- char **well_known = NULL; |
|
- sd_bus_creds *c; |
|
- int r; |
|
- |
|
- assert(a); |
|
- assert(m); |
|
- |
|
- if (!a->is_kernel) |
|
- return 0; |
|
- |
|
- /* We will change the sender of messages from the bus driver |
|
- * so that they originate from the bus driver. This is a |
|
- * speciality originating from dbus1, where the bus driver did |
|
- * not have a unique id, but only the well-known name. */ |
|
- |
|
- c = sd_bus_message_get_creds(m); |
|
- if (!c) |
|
- return 0; |
|
- |
|
- r = sd_bus_creds_get_well_known_names(c, &well_known); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- if (strv_contains(well_known, "org.freedesktop.DBus")) |
|
- m->sender = "org.freedesktop.DBus"; |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-static int proxy_process_destination_to_local(Proxy *p) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL; |
|
- int r; |
|
- |
|
- assert(p); |
|
- |
|
- r = sd_bus_process(p->destination_bus, &m); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */ |
|
- return r; |
|
- if (r < 0) { |
|
- log_error_errno(r, "Failed to process destination bus: %m"); |
|
- return r; |
|
- } |
|
- if (r == 0) |
|
- return 0; |
|
- if (!m) |
|
- return 1; |
|
- |
|
- /* We officially got EOF, let's quit */ |
|
- if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) |
|
- return -ECONNRESET; |
|
- |
|
- r = synthesize_name_acquired(p->destination_bus, p->local_bus, m); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to synthesize message: %m"); |
|
- |
|
- patch_sender(p->destination_bus, m); |
|
- |
|
- if (p->policy) { |
|
- r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to process policy: %m"); |
|
- if (r > 0) |
|
- return 1; |
|
- } |
|
- |
|
- r = sd_bus_send(p->local_bus, m, NULL); |
|
- if (r < 0) { |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- |
|
- /* If the peer tries to send a reply and it is |
|
- * rejected with EPERM by the kernel, we ignore the |
|
- * error. This catches cases where the original |
|
- * method-call didn't had EXPECT_REPLY set, but the |
|
- * proxy-peer still sends a reply. This is allowed in |
|
- * dbus1, but not in kdbus. We don't want to track |
|
- * reply-windows in the proxy, so we simply ignore |
|
- * EPERM for all replies. The only downside is, that |
|
- * callers are no longer notified if their replies are |
|
- * dropped. However, this is equivalent to the |
|
- * caller's timeout to expire, so this should be |
|
- * acceptable. Nobody sane sends replies without a |
|
- * matching method-call, so nobody should care. */ |
|
- if (r == -EPERM && m->reply_cookie > 0) |
|
- return 1; |
|
- |
|
- /* Return the error to the client, if we can */ |
|
- synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m"); |
|
- if (r == -ENOBUFS) { |
|
- /* if local dbus1 peer does not dispatch its queue, warn only once */ |
|
- if (!p->queue_overflow) |
|
- log_error("Dropped messages due to queue overflow of local peer (pid: "PID_FMT" uid: "UID_FMT")", p->local_creds.pid, p->local_creds.uid); |
|
- p->queue_overflow = true; |
|
- } else |
|
- log_error_errno(r, |
|
- "Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m", |
|
- p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type), |
|
- strna(m->destination), strna(m->path), strna(m->interface), strna(m->member)); |
|
- |
|
- return 1; |
|
- } |
|
- |
|
- p->queue_overflow = false; |
|
- return 1; |
|
-} |
|
- |
|
-static int proxy_process_local_to_destination(Proxy *p) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL; |
|
- int r; |
|
- |
|
- assert(p); |
|
- |
|
- r = sd_bus_process(p->local_bus, &m); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */ |
|
- return r; |
|
- if (r < 0) { |
|
- log_error_errno(r, "Failed to process local bus: %m"); |
|
- return r; |
|
- } |
|
- if (r == 0) |
|
- return 0; |
|
- if (!m) |
|
- return 1; |
|
- |
|
- /* We officially got EOF, let's quit */ |
|
- if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) |
|
- return -ECONNRESET; |
|
- |
|
- r = process_hello(p, m); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to process HELLO: %m"); |
|
- if (r > 0) |
|
- return 1; |
|
- |
|
- r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to process driver calls: %m"); |
|
- if (r > 0) |
|
- return 1; |
|
- |
|
- for (;;) { |
|
- if (p->policy) { |
|
- r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- if (r < 0) |
|
- return log_error_errno(r, "Failed to process policy: %m"); |
|
- if (r > 0) |
|
- return 1; |
|
- } |
|
- |
|
- r = sd_bus_send(p->destination_bus, m, NULL); |
|
- if (r < 0) { |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return r; |
|
- |
|
- /* The name database changed since the policy check, hence let's check again */ |
|
- if (r == -EREMCHG) |
|
- continue; |
|
- |
|
- /* see above why EPERM is ignored for replies */ |
|
- if (r == -EPERM && m->reply_cookie > 0) |
|
- return 1; |
|
- |
|
- synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m"); |
|
- log_error_errno(r, |
|
- "Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m", |
|
- p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type), |
|
- strna(m->destination), strna(m->path), strna(m->interface), strna(m->member)); |
|
- return 1; |
|
- } |
|
- |
|
- break; |
|
- } |
|
- |
|
- return 1; |
|
-} |
|
- |
|
-int proxy_run(Proxy *p) { |
|
- int r; |
|
- |
|
- assert(p); |
|
- |
|
- for (;;) { |
|
- bool busy = false; |
|
- |
|
- if (p->got_hello) { |
|
- /* Read messages from bus, to pass them on to our client */ |
|
- r = proxy_process_destination_to_local(p); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return 0; |
|
- if (r < 0) |
|
- return r; |
|
- if (r > 0) |
|
- busy = true; |
|
- } |
|
- |
|
- /* Read messages from our client, to pass them on to the bus */ |
|
- r = proxy_process_local_to_destination(p); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return 0; |
|
- if (r < 0) |
|
- return r; |
|
- if (r > 0) |
|
- busy = true; |
|
- |
|
- if (!busy) { |
|
- r = proxy_wait(p); |
|
- if (r == -ECONNRESET || r == -ENOTCONN) |
|
- return 0; |
|
- if (r < 0) |
|
- return r; |
|
- } |
|
- } |
|
- |
|
- return 0; |
|
-} |
|
diff --git a/src/bus-proxyd/proxy.h b/src/bus-proxyd/proxy.h |
|
deleted file mode 100644 |
|
index 782c4e60b3..0000000000 |
|
--- a/src/bus-proxyd/proxy.h |
|
+++ /dev/null |
|
@@ -1,53 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-#pragma once |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2014 David Herrmann |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <stdlib.h> |
|
-#include "sd-bus.h" |
|
-#include "bus-xml-policy.h" |
|
-#include "util.h" |
|
- |
|
-typedef struct Proxy Proxy; |
|
- |
|
-struct Proxy { |
|
- sd_bus *local_bus; |
|
- struct ucred local_creds; |
|
- int local_in; |
|
- int local_out; |
|
- |
|
- sd_bus *destination_bus; |
|
- |
|
- Set *owned_names; |
|
- SharedPolicy *policy; |
|
- |
|
- bool got_hello : 1; |
|
- bool queue_overflow : 1; |
|
-}; |
|
- |
|
-int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest); |
|
-Proxy *proxy_free(Proxy *p); |
|
- |
|
-int proxy_set_policy(Proxy *p, SharedPolicy *policy, char **configuration); |
|
-int proxy_hello_policy(Proxy *p, uid_t original_uid); |
|
-int proxy_run(Proxy *p); |
|
- |
|
-DEFINE_TRIVIAL_CLEANUP_FUNC(Proxy*, proxy_free); |
|
diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c |
|
deleted file mode 100644 |
|
index 9fb3e9fc49..0000000000 |
|
--- a/src/bus-proxyd/stdio-bridge.c |
|
+++ /dev/null |
|
@@ -1,263 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2010 Lennart Poettering |
|
- Copyright 2013 Daniel Mack |
|
- Copyright 2014 Kay Sievers |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <sys/socket.h> |
|
-#include <sys/un.h> |
|
-#include <sys/types.h> |
|
-#include <fcntl.h> |
|
-#include <unistd.h> |
|
-#include <string.h> |
|
-#include <errno.h> |
|
-#include <poll.h> |
|
-#include <stddef.h> |
|
-#include <getopt.h> |
|
- |
|
-#include "log.h" |
|
-#include "util.h" |
|
-#include "socket-util.h" |
|
-#include "sd-daemon.h" |
|
-#include "sd-bus.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-util.h" |
|
-#include "build.h" |
|
-#include "strv.h" |
|
-#include "def.h" |
|
-#include "capability.h" |
|
-#include "bus-control.h" |
|
-#include "smack-util.h" |
|
-#include "set.h" |
|
-#include "bus-xml-policy.h" |
|
-#include "driver.h" |
|
-#include "proxy.h" |
|
-#include "synthesize.h" |
|
- |
|
-static char *arg_address = NULL; |
|
-static char *arg_command_line_buffer = NULL; |
|
- |
|
-static int help(void) { |
|
- |
|
- printf("%s [OPTIONS...]\n\n" |
|
- "Connect STDIO to a given bus address.\n\n" |
|
- " -h --help Show this help\n" |
|
- " --version Show package version\n" |
|
- " --machine=MACHINE Connect to specified machine\n" |
|
- " --address=ADDRESS Connect to the bus specified by ADDRESS\n" |
|
- " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n", |
|
- program_invocation_short_name); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-static int parse_argv(int argc, char *argv[]) { |
|
- |
|
- enum { |
|
- ARG_VERSION = 0x100, |
|
- ARG_ADDRESS, |
|
- ARG_MACHINE, |
|
- }; |
|
- |
|
- static const struct option options[] = { |
|
- { "help", no_argument, NULL, 'h' }, |
|
- { "version", no_argument, NULL, ARG_VERSION }, |
|
- { "address", required_argument, NULL, ARG_ADDRESS }, |
|
- { "machine", required_argument, NULL, ARG_MACHINE }, |
|
- {}, |
|
- }; |
|
- |
|
- int c; |
|
- |
|
- assert(argc >= 0); |
|
- assert(argv); |
|
- |
|
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) |
|
- |
|
- switch (c) { |
|
- |
|
- case 'h': |
|
- help(); |
|
- return 0; |
|
- |
|
- case ARG_VERSION: |
|
- puts(PACKAGE_STRING); |
|
- puts(SYSTEMD_FEATURES); |
|
- return 0; |
|
- |
|
- case ARG_ADDRESS: { |
|
- char *a; |
|
- |
|
- a = strdup(optarg); |
|
- if (!a) |
|
- return log_oom(); |
|
- |
|
- free(arg_address); |
|
- arg_address = a; |
|
- break; |
|
- } |
|
- |
|
- case ARG_MACHINE: { |
|
- _cleanup_free_ char *e = NULL; |
|
- char *a; |
|
- |
|
- e = bus_address_escape(optarg); |
|
- if (!e) |
|
- return log_oom(); |
|
- |
|
-#ifdef ENABLE_KDBUS |
|
- a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); |
|
-#else |
|
- a = strjoin("x-machine-unix:machine=", e, NULL); |
|
-#endif |
|
- if (!a) |
|
- return log_oom(); |
|
- |
|
- free(arg_address); |
|
- arg_address = a; |
|
- |
|
- break; |
|
- } |
|
- |
|
- case '?': |
|
- return -EINVAL; |
|
- |
|
- default: |
|
- assert_not_reached("Unhandled option"); |
|
- } |
|
- |
|
- /* If the first command line argument is only "x" characters |
|
- * we'll write who we are talking to into it, so that "ps" is |
|
- * explanatory */ |
|
- arg_command_line_buffer = argv[optind]; |
|
- if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) { |
|
- log_error("Too many arguments"); |
|
- return -EINVAL; |
|
- } |
|
- |
|
- if (!arg_address) { |
|
- arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS); |
|
- if (!arg_address) |
|
- return log_oom(); |
|
- } |
|
- |
|
- return 1; |
|
-} |
|
- |
|
-static int rename_service(sd_bus *a, sd_bus *b) { |
|
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; |
|
- _cleanup_free_ char *p = NULL, *name = NULL; |
|
- const char *comm; |
|
- char **cmdline; |
|
- uid_t uid; |
|
- pid_t pid; |
|
- int r; |
|
- |
|
- assert(a); |
|
- assert(b); |
|
- |
|
- r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = sd_bus_creds_get_euid(creds, &uid); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = sd_bus_creds_get_pid(creds, &pid); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = sd_bus_creds_get_cmdline(creds, &cmdline); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = sd_bus_creds_get_comm(creds, &comm); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- name = uid_to_name(uid); |
|
- if (!name) |
|
- return -ENOMEM; |
|
- |
|
- p = strv_join(cmdline, " "); |
|
- if (!p) |
|
- return -ENOMEM; |
|
- |
|
- /* The status string gets the full command line ... */ |
|
- sd_notifyf(false, |
|
- "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)", |
|
- pid, p, |
|
- uid, name); |
|
- |
|
- /* ... and the argv line only the short comm */ |
|
- if (arg_command_line_buffer) { |
|
- size_t m, w; |
|
- |
|
- m = strlen(arg_command_line_buffer); |
|
- w = snprintf(arg_command_line_buffer, m, |
|
- "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]", |
|
- pid, comm, |
|
- uid, name); |
|
- |
|
- if (m > w) |
|
- memzero(arg_command_line_buffer + w, m - w); |
|
- } |
|
- |
|
- log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s", |
|
- pid, p, |
|
- uid, name, |
|
- a->unique_name); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-int main(int argc, char *argv[]) { |
|
- _cleanup_(proxy_freep) Proxy *p = NULL; |
|
- int r; |
|
- |
|
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); |
|
- log_parse_environment(); |
|
- log_open(); |
|
- |
|
- r = parse_argv(argc, argv); |
|
- if (r <= 0) |
|
- goto finish; |
|
- |
|
- r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address); |
|
- if (r < 0) |
|
- goto finish; |
|
- |
|
- r = rename_service(p->destination_bus, p->local_bus); |
|
- if (r < 0) |
|
- log_debug_errno(r, "Failed to rename process: %m"); |
|
- |
|
- r = proxy_run(p); |
|
- |
|
-finish: |
|
- sd_notify(false, |
|
- "STOPPING=1\n" |
|
- "STATUS=Shutting down."); |
|
- |
|
- free(arg_address); |
|
- |
|
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
|
-} |
|
diff --git a/src/bus-proxyd/synthesize.c b/src/bus-proxyd/synthesize.c |
|
deleted file mode 100644 |
|
index e1b0fd3535..0000000000 |
|
--- a/src/bus-proxyd/synthesize.c |
|
+++ /dev/null |
|
@@ -1,228 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2010 Lennart Poettering |
|
- Copyright 2013 Daniel Mack |
|
- Copyright 2014 Kay Sievers |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <sys/types.h> |
|
-#include <unistd.h> |
|
-#include <string.h> |
|
-#include <errno.h> |
|
-#include <stddef.h> |
|
- |
|
-#include "log.h" |
|
-#include "util.h" |
|
-#include "sd-bus.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-util.h" |
|
-#include "strv.h" |
|
-#include "def.h" |
|
-#include "bus-control.h" |
|
-#include "synthesize.h" |
|
- |
|
-static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) { |
|
- int r; |
|
- |
|
- assert(b); |
|
- assert(m); |
|
- |
|
- r = bus_message_append_sender(m, "org.freedesktop.DBus"); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = bus_seal_synthetic_message(b, m); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- return sd_bus_send(b, m, NULL); |
|
-} |
|
- |
|
-int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL; |
|
- int r; |
|
- |
|
- assert(call); |
|
- |
|
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) |
|
- return 0; |
|
- |
|
- r = sd_bus_message_new_method_error(call, &m, e); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- return synthetic_driver_send(call->bus, m); |
|
-} |
|
- |
|
-int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) { |
|
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
- va_list ap; |
|
- |
|
- va_start(ap, format); |
|
- bus_error_setfv(&error, name, format, ap); |
|
- va_end(ap); |
|
- |
|
- return synthetic_reply_method_error(call, &error); |
|
-} |
|
- |
|
-int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) { |
|
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL; |
|
- |
|
- assert(call); |
|
- |
|
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) |
|
- return 0; |
|
- |
|
- if (sd_bus_error_is_set(p)) |
|
- return synthetic_reply_method_error(call, p); |
|
- |
|
- sd_bus_error_set_errno(&berror, error); |
|
- |
|
- return synthetic_reply_method_error(call, &berror); |
|
-} |
|
- |
|
-int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) { |
|
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL; |
|
- va_list ap; |
|
- |
|
- assert(call); |
|
- |
|
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) |
|
- return 0; |
|
- |
|
- va_start(ap, format); |
|
- sd_bus_error_set_errnofv(&berror, error, format, ap); |
|
- va_end(ap); |
|
- |
|
- return synthetic_reply_method_error(call, &berror); |
|
-} |
|
- |
|
-int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL; |
|
- int r; |
|
- |
|
- assert(call); |
|
- |
|
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) |
|
- return 0; |
|
- |
|
- r = sd_bus_message_new_method_return(call, &m); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- if (!isempty(types)) { |
|
- va_list ap; |
|
- |
|
- va_start(ap, types); |
|
- r = bus_message_append_ap(m, types, ap); |
|
- va_end(ap); |
|
- if (r < 0) |
|
- return r; |
|
- } |
|
- |
|
- return synthetic_driver_send(call->bus, m); |
|
-} |
|
- |
|
-int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL; |
|
- int r; |
|
- |
|
- assert(call); |
|
- |
|
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) |
|
- return 0; |
|
- |
|
- r = sd_bus_message_new_method_return(call, &m); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(call, r, NULL); |
|
- |
|
- r = sd_bus_message_append_strv(m, l); |
|
- if (r < 0) |
|
- return synthetic_reply_method_errno(call, r, NULL); |
|
- |
|
- return synthetic_driver_send(call->bus, m); |
|
-} |
|
- |
|
-int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) { |
|
- _cleanup_bus_message_unref_ sd_bus_message *n = NULL; |
|
- const char *name, *old_owner, *new_owner; |
|
- int r; |
|
- |
|
- assert(a); |
|
- assert(b); |
|
- assert(m); |
|
- |
|
- /* If we get NameOwnerChanged for our own name, we need to |
|
- * synthesize NameLost/NameAcquired, since socket clients need |
|
- * that, even though it is obsoleted on kdbus */ |
|
- |
|
- if (!a->is_kernel) |
|
- return 0; |
|
- |
|
- if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") || |
|
- !streq_ptr(m->path, "/org/freedesktop/DBus") || |
|
- !streq_ptr(m->sender, "org.freedesktop.DBus")) |
|
- return 0; |
|
- |
|
- r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = sd_bus_message_rewind(m, true); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- if (streq(old_owner, a->unique_name)) { |
|
- |
|
- r = sd_bus_message_new_signal( |
|
- b, |
|
- &n, |
|
- "/org/freedesktop/DBus", |
|
- "org.freedesktop.DBus", |
|
- "NameLost"); |
|
- |
|
- } else if (streq(new_owner, a->unique_name)) { |
|
- |
|
- r = sd_bus_message_new_signal( |
|
- b, |
|
- &n, |
|
- "/org/freedesktop/DBus", |
|
- "org.freedesktop.DBus", |
|
- "NameAcquired"); |
|
- } else |
|
- return 0; |
|
- |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = sd_bus_message_append(n, "s", name); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = bus_message_append_sender(n, "org.freedesktop.DBus"); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- r = bus_seal_synthetic_message(b, n); |
|
- if (r < 0) |
|
- return r; |
|
- |
|
- return sd_bus_send(b, n, NULL); |
|
-} |
|
diff --git a/src/bus-proxyd/synthesize.h b/src/bus-proxyd/synthesize.h |
|
deleted file mode 100644 |
|
index a55f171cb2..0000000000 |
|
--- a/src/bus-proxyd/synthesize.h |
|
+++ /dev/null |
|
@@ -1,34 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-#pragma once |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2014 Lennart Poettering |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include "sd-bus.h" |
|
- |
|
-int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...); |
|
-int synthetic_reply_method_return_strv(sd_bus_message *call, char **l); |
|
- |
|
-int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e); |
|
-int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4); |
|
-int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p); |
|
-int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4); |
|
- |
|
-int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m); |
|
diff --git a/src/bus-proxyd/test-bus-xml-policy.c b/src/bus-proxyd/test-bus-xml-policy.c |
|
deleted file mode 100644 |
|
index 421487e038..0000000000 |
|
--- a/src/bus-proxyd/test-bus-xml-policy.c |
|
+++ /dev/null |
|
@@ -1,182 +0,0 @@ |
|
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
|
- |
|
-/*** |
|
- This file is part of systemd. |
|
- |
|
- Copyright 2014 Daniel Mack |
|
- |
|
- systemd is free software; you can redistribute it and/or modify it |
|
- under the terms of the GNU Lesser General Public License as published by |
|
- the Free Software Foundation; either version 2.1 of the License, or |
|
- (at your option) any later version. |
|
- |
|
- systemd 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 |
|
- Lesser General Public License for more details. |
|
- |
|
- You should have received a copy of the GNU Lesser General Public License |
|
- along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
-***/ |
|
- |
|
-#include <sys/socket.h> |
|
-#include <sys/un.h> |
|
-#include <sys/types.h> |
|
-#include <fcntl.h> |
|
-#include <unistd.h> |
|
-#include <string.h> |
|
-#include <errno.h> |
|
-#include <poll.h> |
|
-#include <stddef.h> |
|
-#include <getopt.h> |
|
- |
|
-#include "log.h" |
|
-#include "util.h" |
|
-#include "sd-bus.h" |
|
-#include "bus-internal.h" |
|
-#include "bus-message.h" |
|
-#include "bus-util.h" |
|
-#include "build.h" |
|
-#include "strv.h" |
|
-#include "def.h" |
|
-#include "capability.h" |
|
-#include "bus-xml-policy.h" |
|
- |
|
-static int test_policy_load(Policy *p, const char *name) { |
|
- _cleanup_free_ char *path = NULL; |
|
- int r = 0; |
|
- |
|
- path = strjoin(TEST_DIR, "/bus-policy/", name, NULL); |
|
- assert_se(path); |
|
- |
|
- if (access(path, R_OK) == 0) |
|
- r = policy_load(p, STRV_MAKE(path)); |
|
- else |
|
- r = -ENOENT; |
|
- |
|
- return r; |
|
-} |
|
- |
|
-static int show_policy(const char *fn) { |
|
- Policy p = {}; |
|
- int r; |
|
- |
|
- r = policy_load(&p, STRV_MAKE(fn)); |
|
- if (r < 0) { |
|
- log_error_errno(r, "Failed to load policy %s: %m", fn); |
|
- return r; |
|
- } |
|
- |
|
- policy_dump(&p); |
|
- policy_free(&p); |
|
- |
|
- return 0; |
|
-} |
|
- |
|
-int main(int argc, char *argv[]) { |
|
- |
|
- Policy p = {}; |
|
- |
|
- printf("Showing session policy BEGIN\n"); |
|
- show_policy("/etc/dbus-1/session.conf"); |
|
- printf("Showing session policy END\n"); |
|
- |
|
- printf("Showing system policy BEGIN\n"); |
|
- show_policy("/etc/dbus-1/system.conf"); |
|
- printf("Showing system policy END\n"); |
|
- |
|
- /* Ownership tests */ |
|
- assert_se(test_policy_load(&p, "ownerships.conf") == 0); |
|
- |
|
- assert_se(policy_check_own(&p, 0, 0, "org.test.test1") == true); |
|
- assert_se(policy_check_own(&p, 1, 0, "org.test.test1") == true); |
|
- |
|
- assert_se(policy_check_own(&p, 0, 0, "org.test.test2") == true); |
|
- assert_se(policy_check_own(&p, 1, 0, "org.test.test2") == false); |
|
- |
|
- assert_se(policy_check_own(&p, 0, 0, "org.test.test3") == false); |
|
- assert_se(policy_check_own(&p, 1, 0, "org.test.test3") == false); |
|
- |
|
- assert_se(policy_check_own(&p, 0, 0, "org.test.test4") == false); |
|
- assert_se(policy_check_own(&p, 1, 0, "org.test.test4") == true); |
|
- |
|
- policy_free(&p); |
|
- |
|
- /* Signaltest */ |
|
- assert_se(test_policy_load(&p, "signals.conf") == 0); |
|
- |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == true); |
|
- assert_se(policy_check_one_send(&p, 1, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == false); |
|
- |
|
- policy_free(&p); |
|
- |
|
- /* Method calls */ |
|
- assert_se(test_policy_load(&p, "methods.conf") == 0); |
|
- policy_dump(&p); |
|
- |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int1", "Member") == true); |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == true); |
|
- |
|
- assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test3", "/an/object/path", "org.test.int3", "Member111") == true); |
|
- |
|
- policy_free(&p); |
|
- |
|
- /* User and groups */ |
|
- assert_se(test_policy_load(&p, "hello.conf") == 0); |
|
- policy_dump(&p); |
|
- |
|
- assert_se(policy_check_hello(&p, 0, 0) == true); |
|
- assert_se(policy_check_hello(&p, 1, 0) == false); |
|
- assert_se(policy_check_hello(&p, 0, 1) == false); |
|
- |
|
- policy_free(&p); |
|
- |
|
- /* dbus1 test file: ownership */ |
|
- |
|
- assert_se(test_policy_load(&p, "check-own-rules.conf") >= 0); |
|
- policy_dump(&p); |
|
- |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop") == false); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystem") == false); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems") == true); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo") == true); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo.bar") == true); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2") == false); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo") == false); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo.bar") == false); |
|
- |
|
- policy_free(&p); |
|
- |
|
- /* dbus1 test file: many rules */ |
|
- |
|
- assert_se(test_policy_load(&p, "many-rules.conf") >= 0); |
|
- policy_dump(&p); |
|
- policy_free(&p); |
|
- |
|
- /* dbus1 test file: generic test */ |
|
- |
|
- assert_se(test_policy_load(&p, "test.conf") >= 0); |
|
- policy_dump(&p); |
|
- |
|
- assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService") == true); |
|
- assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService2") == false); |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); |
|
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); |
|
- assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); |
|
- assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); |
|
- assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); |
|
- |
|
- assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService") == false); |
|
- assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService2") == false); |
|
- assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); |
|
- assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); |
|
- assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); |
|
- assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); |
|
- assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); |
|
- |
|
- policy_free(&p); |
|
- |
|
- return EXIT_SUCCESS; |
|
-} |
|
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c |
|
new file mode 100644 |
|
index 0000000000..791e545aba |
|
--- /dev/null |
|
+++ b/src/stdio-bridge/stdio-bridge.c |
|
@@ -0,0 +1,303 @@ |
|
+/*** |
|
+ This file is part of systemd. |
|
+ |
|
+ Copyright 2010 Lennart Poettering |
|
+ |
|
+ systemd is free software; you can redistribute it and/or modify it |
|
+ under the terms of the GNU Lesser General Public License as published by |
|
+ the Free Software Foundation; either version 2.1 of the License, or |
|
+ (at your option) any later version. |
|
+ |
|
+ systemd 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 |
|
+ Lesser General Public License for more details. |
|
+ |
|
+ You should have received a copy of the GNU Lesser General Public License |
|
+ along with systemd; If not, see <http://www.gnu.org/licenses/>. |
|
+***/ |
|
+ |
|
+#include <errno.h> |
|
+#include <getopt.h> |
|
+#include <poll.h> |
|
+#include <stddef.h> |
|
+#include <string.h> |
|
+#include <unistd.h> |
|
+ |
|
+#include "sd-bus.h" |
|
+#include "sd-daemon.h" |
|
+ |
|
+#include "bus-internal.h" |
|
+#include "bus-util.h" |
|
+#include "build.h" |
|
+#include "log.h" |
|
+#include "util.h" |
|
+ |
|
+#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket" |
|
+ |
|
+const char *arg_bus_path = DEFAULT_BUS_PATH; |
|
+ |
|
+static int help(void) { |
|
+ |
|
+ printf("%s [OPTIONS...]\n\n" |
|
+ "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n" |
|
+ " -h --help Show this help\n" |
|
+ " --version Show package version\n" |
|
+ " --bus-path=PATH Path to the kernel bus (default: %s)\n", |
|
+ program_invocation_short_name, DEFAULT_BUS_PATH); |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
+static int parse_argv(int argc, char *argv[]) { |
|
+ |
|
+ enum { |
|
+ ARG_VERSION = 0x100, |
|
+ }; |
|
+ |
|
+ static const struct option options[] = { |
|
+ { "help", no_argument, NULL, 'h' }, |
|
+ { "bus-path", required_argument, NULL, 'p' }, |
|
+ { NULL, 0, NULL, 0 } |
|
+ }; |
|
+ |
|
+ int c; |
|
+ |
|
+ assert(argc >= 0); |
|
+ assert(argv); |
|
+ |
|
+ while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) { |
|
+ |
|
+ switch (c) { |
|
+ |
|
+ case 'h': |
|
+ help(); |
|
+ return 0; |
|
+ |
|
+ case ARG_VERSION: |
|
+ puts(PACKAGE_STRING); |
|
+ puts(SYSTEMD_FEATURES); |
|
+ return 0; |
|
+ |
|
+ case '?': |
|
+ return -EINVAL; |
|
+ |
|
+ case 'p': |
|
+ arg_bus_path = optarg; |
|
+ break; |
|
+ |
|
+ default: |
|
+ log_error("Unknown option code %c", c); |
|
+ return -EINVAL; |
|
+ } |
|
+ } |
|
+ |
|
+ return 1; |
|
+} |
|
+ |
|
+int main(int argc, char *argv[]) { |
|
+ _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL; |
|
+ sd_id128_t server_id; |
|
+ bool is_unix; |
|
+ int r, in_fd, out_fd; |
|
+ |
|
+ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); |
|
+ log_parse_environment(); |
|
+ log_open(); |
|
+ |
|
+ r = parse_argv(argc, argv); |
|
+ if (r <= 0) |
|
+ goto finish; |
|
+ |
|
+ r = sd_listen_fds(0); |
|
+ if (r == 0) { |
|
+ in_fd = STDIN_FILENO; |
|
+ out_fd = STDOUT_FILENO; |
|
+ } else if (r == 1) { |
|
+ in_fd = SD_LISTEN_FDS_START; |
|
+ out_fd = SD_LISTEN_FDS_START; |
|
+ } else { |
|
+ log_error("Illegal number of file descriptors passed\n"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ is_unix = |
|
+ sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && |
|
+ sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0; |
|
+ |
|
+ r = sd_bus_new(&a); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to allocate bus: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_set_address(a, arg_bus_path); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to set address to connect to: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_negotiate_fds(a, is_unix); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to set FD negotiation: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_start(a); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to start bus client: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_get_bus_id(a, &server_id); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to get server ID: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_new(&b); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to allocate bus: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_set_fd(b, in_fd, out_fd); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to set fds: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_set_server(b, 1, server_id); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to set server mode: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_negotiate_fds(b, is_unix); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to set FD negotiation: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_set_anonymous(b, true); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to set anonymous authentication: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_start(b); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to start bus client: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ for (;;) { |
|
+ _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL; |
|
+ int events_a, events_b, fd; |
|
+ uint64_t timeout_a, timeout_b, t; |
|
+ struct timespec _ts, *ts; |
|
+ |
|
+ r = sd_bus_process(a, &m); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to process bus a: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ if (m) { |
|
+ r = sd_bus_send(b, m, NULL); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to send message: %m"); |
|
+ goto finish; |
|
+ } |
|
+ } |
|
+ |
|
+ if (r > 0) |
|
+ continue; |
|
+ |
|
+ r = sd_bus_process(b, &m); |
|
+ if (r < 0) { |
|
+ /* treat 'connection reset by peer' as clean exit condition */ |
|
+ if (r == -ECONNRESET) |
|
+ r = 0; |
|
+ |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ if (m) { |
|
+ r = sd_bus_send(a, m, NULL); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to send message: %m"); |
|
+ goto finish; |
|
+ } |
|
+ } |
|
+ |
|
+ if (r > 0) |
|
+ continue; |
|
+ |
|
+ fd = sd_bus_get_fd(a); |
|
+ if (fd < 0) { |
|
+ log_error_errno(r, "Failed to get fd: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ events_a = sd_bus_get_events(a); |
|
+ if (events_a < 0) { |
|
+ log_error_errno(r, "Failed to get events mask: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_get_timeout(a, &timeout_a); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to get timeout: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ events_b = sd_bus_get_events(b); |
|
+ if (events_b < 0) { |
|
+ log_error_errno(r, "Failed to get events mask: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ r = sd_bus_get_timeout(b, &timeout_b); |
|
+ if (r < 0) { |
|
+ log_error_errno(r, "Failed to get timeout: %m"); |
|
+ goto finish; |
|
+ } |
|
+ |
|
+ t = timeout_a; |
|
+ if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a)) |
|
+ t = timeout_b; |
|
+ |
|
+ if (t == (uint64_t) -1) |
|
+ ts = NULL; |
|
+ else { |
|
+ usec_t nw; |
|
+ |
|
+ nw = now(CLOCK_MONOTONIC); |
|
+ if (t > nw) |
|
+ t -= nw; |
|
+ else |
|
+ t = 0; |
|
+ |
|
+ ts = timespec_store(&_ts, t); |
|
+ } |
|
+ |
|
+ { |
|
+ struct pollfd p[3] = { |
|
+ {.fd = fd, .events = events_a, }, |
|
+ {.fd = STDIN_FILENO, .events = events_b & POLLIN, }, |
|
+ {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }}; |
|
+ |
|
+ r = ppoll(p, ELEMENTSOF(p), ts, NULL); |
|
+ } |
|
+ if (r < 0) { |
|
+ log_error("ppoll() failed: %m"); |
|
+ goto finish; |
|
+ } |
|
+ } |
|
+ |
|
+ r = 0; |
|
+ |
|
+finish: |
|
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
|
+} |
|
diff --git a/src/test/test-tables.c b/src/test/test-tables.c |
|
index e4097903c4..afd4ab7fb3 100644 |
|
--- a/src/test/test-tables.c |
|
+++ b/src/test/test-tables.c |
|
@@ -46,7 +46,6 @@ |
|
#include "util.h" |
|
#include "architecture.h" |
|
#include "link-config.h" |
|
-#include "bus-xml-policy.h" |
|
#include "busname.h" |
|
#include "journald-server.h" |
|
#include "locale-util.h" |
|
@@ -86,8 +85,6 @@ int main(int argc, char **argv) { |
|
test_table(path_result, PATH_RESULT); |
|
test_table(path_state, PATH_STATE); |
|
test_table(path_type, PATH_TYPE); |
|
- test_table(policy_item_class, POLICY_ITEM_CLASS); |
|
- test_table(policy_item_type, POLICY_ITEM_TYPE); |
|
test_table(protect_home, PROTECT_HOME); |
|
test_table(protect_system, PROTECT_SYSTEM); |
|
test_table(rlimit, RLIMIT); |
|
diff --git a/sysusers.d/systemd.conf.m4 b/sysusers.d/systemd.conf.m4 |
|
index 23175de1f5..3d3e2374ef 100644 |
|
--- a/sysusers.d/systemd.conf.m4 |
|
+++ b/sysusers.d/systemd.conf.m4 |
|
@@ -6,9 +6,6 @@ |
|
# (at your option) any later version. |
|
|
|
g systemd-journal - - |
|
-m4_ifdef(`ENABLE_KDBUS', |
|
-u systemd-bus-proxy - "systemd Bus Proxy" |
|
-)m4_dnl |
|
m4_ifdef(`ENABLE_NETWORKD', |
|
u systemd-network - "systemd Network Management" |
|
)m4_dnl |
|
diff --git a/units/.gitignore b/units/.gitignore |
|
index 7f3e0d093c..48c8f72174 100644 |
|
--- a/units/.gitignore |
|
+++ b/units/.gitignore |
|
@@ -1,4 +1,3 @@ |
|
-/systemd-bus-proxyd.service.m4 |
|
/user@.service.m4 |
|
/console-getty.service |
|
/console-getty.service.m4 |
|
@@ -24,7 +23,6 @@ |
|
/systemd-backlight@.service |
|
/systemd-binfmt.service |
|
/systemd-bootchart.service |
|
-/systemd-bus-proxyd.service |
|
/systemd-firstboot.service |
|
/systemd-fsck-root.service |
|
/systemd-fsck@.service |
|
diff --git a/units/systemd-bus-proxyd.service.m4.in b/units/systemd-bus-proxyd.service.m4.in |
|
deleted file mode 100644 |
|
index ffaf0bdc87..0000000000 |
|
--- a/units/systemd-bus-proxyd.service.m4.in |
|
+++ /dev/null |
|
@@ -1,19 +0,0 @@ |
|
-# This file is part of systemd. |
|
-# |
|
-# systemd is free software; you can redistribute it and/or modify it |
|
-# under the terms of the GNU Lesser General Public License as published by |
|
-# the Free Software Foundation; either version 2.1 of the License, or |
|
-# (at your option) any later version. |
|
- |
|
-[Unit] |
|
-Description=Legacy D-Bus Protocol Compatibility Daemon |
|
- |
|
-[Service] |
|
-ExecStart=@rootlibexecdir@/systemd-bus-proxyd --address=kernel:path=/sys/fs/kdbus/0-system/bus |
|
-NotifyAccess=main |
|
-CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP m4_ifdef(`HAVE_SMACK', CAP_MAC_ADMIN ) |
|
-PrivateTmp=yes |
|
-PrivateDevices=yes |
|
-PrivateNetwork=yes |
|
-ProtectSystem=full |
|
-ProtectHome=yes |
|
diff --git a/units/systemd-bus-proxyd.socket b/units/systemd-bus-proxyd.socket |
|
deleted file mode 100644 |
|
index 3f80a1d547..0000000000 |
|
--- a/units/systemd-bus-proxyd.socket |
|
+++ /dev/null |
|
@@ -1,12 +0,0 @@ |
|
-# This file is part of systemd. |
|
-# |
|
-# systemd is free software; you can redistribute it and/or modify it |
|
-# under the terms of the GNU Lesser General Public License as published by |
|
-# the Free Software Foundation; either version 2.1 of the License, or |
|
-# (at your option) any later version. |
|
- |
|
-[Unit] |
|
-Description=Legacy D-Bus Protocol Compatibility Socket |
|
- |
|
-[Socket] |
|
-ListenStream=/var/run/dbus/system_bus_socket |
|
diff --git a/units/user/.gitignore b/units/user/.gitignore |
|
index 6111b10ccf..41a74f5461 100644 |
|
--- a/units/user/.gitignore |
|
+++ b/units/user/.gitignore |
|
@@ -1,3 +1 @@ |
|
/systemd-exit.service |
|
-/systemd-bus-proxyd.service |
|
-/systemd-consoled.service |
|
diff --git a/units/user/systemd-bus-proxyd.service.in b/units/user/systemd-bus-proxyd.service.in |
|
deleted file mode 100644 |
|
index e1e399dc32..0000000000 |
|
--- a/units/user/systemd-bus-proxyd.service.in |
|
+++ /dev/null |
|
@@ -1,13 +0,0 @@ |
|
-# This file is part of systemd. |
|
-# |
|
-# systemd is free software; you can redistribute it and/or modify it |
|
-# under the terms of the GNU Lesser General Public License as published by |
|
-# the Free Software Foundation; either version 2.1 of the License, or |
|
-# (at your option) any later version. |
|
- |
|
-[Unit] |
|
-Description=Legacy D-Bus Protocol Compatibility Daemon |
|
- |
|
-[Service] |
|
-ExecStart=@rootlibexecdir@/systemd-bus-proxyd --address=kernel:path=/sys/fs/kdbus/%U-user/bus |
|
-NotifyAccess=main |
|
diff --git a/units/user/systemd-bus-proxyd.socket b/units/user/systemd-bus-proxyd.socket |
|
deleted file mode 100644 |
|
index b9efc0e7ce..0000000000 |
|
--- a/units/user/systemd-bus-proxyd.socket |
|
+++ /dev/null |
|
@@ -1,12 +0,0 @@ |
|
-# This file is part of systemd. |
|
-# |
|
-# systemd is free software; you can redistribute it and/or modify it |
|
-# under the terms of the GNU Lesser General Public License as published by |
|
-# the Free Software Foundation; either version 2.1 of the License, or |
|
-# (at your option) any later version. |
|
- |
|
-[Unit] |
|
-Description=Legacy D-Bus Protocol Compatibility Socket |
|
- |
|
-[Socket] |
|
-ListenStream=%t/bus
|
|
|