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.
5067 lines
183 KiB
5067 lines
183 KiB
7 years ago
|
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 0360f7c6b..5ac188bfb 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 7ec709c8b..734c80598 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 b347aed7d..924b34b69 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 ffc2cf9f2..bf75909f8 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 498d82c21..99473078a 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 0635280ea..c68fe236c 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 e0efe9985..000000000
|
||
|
--- 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 dc4f07ff1..000000000
|
||
|
--- 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 d0b0e8e00..000000000
|
||
|
--- 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 b6550ed3c..000000000
|
||
|
--- 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 f6ac0c009..000000000
|
||
|
--- 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 f2ec1bbea..000000000
|
||
|
--- 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 bc2c0c86f..000000000
|
||
|
--- 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 b8cedf5ce..000000000
|
||
|
--- 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 e13cf5e2e..000000000
|
||
|
--- 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 782c4e60b..000000000
|
||
|
--- 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 9fb3e9fc4..000000000
|
||
|
--- 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 e1b0fd353..000000000
|
||
|
--- 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 a55f171cb..000000000
|
||
|
--- 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 421487e03..000000000
|
||
|
--- 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 000000000..791e545ab
|
||
|
--- /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 e4097903c..afd4ab7fb 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 23175de1f..3d3e2374e 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 7f3e0d093..48c8f7217 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 ffaf0bdc8..000000000
|
||
|
--- 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 3f80a1d54..000000000
|
||
|
--- 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 6111b10cc..41a74f546 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 e1e399dc3..000000000
|
||
|
--- 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 b9efc0e7c..000000000
|
||
|
--- 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
|