summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-06-20 10:43:24 +0200
committerDaiki Ueno <ueno@gnu.org>2018-06-20 13:19:23 +0200
commit53a7e915b2694bc1957d98493a7aee9abfa3c6c5 (patch)
tree82d4bdce9a6d8559a698cd40fda4bb96990489c7
parentd4a4039f97b2e1f67d09d7cd8c05fb2dd129b23c (diff)
server: Enable socket activation through systemd
This enables socket activation of "p11-kit server" through systemd. The feature provided is essentially the same as commit a4fb2bb5 (reverted), but implemented with "p11-kit server" and libsystemd API instead of wrapping "p11-kit remote" in the unit file. Note that, while it exposes all tokens through the socket, it doesn't increase attack surface beyond the PKCS#11 binary interface provided by p11-kit-proxy.so, because the service is per-user.
-rw-r--r--.gitignore2
-rw-r--r--configure.ac23
-rw-r--r--p11-kit/Makefile.am22
-rw-r--r--p11-kit/p11-kit-server.service.in15
-rw-r--r--p11-kit/p11-kit-server.socket11
-rw-r--r--p11-kit/server.c33
6 files changed, 96 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index 5fd14b8..a94118d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -97,7 +97,7 @@ x86_64-w64-mingw32
/p11-kit/p11-kit.pc
/p11-kit/p11-kit-1.pc
/p11-kit/pkcs11.conf.example
-/p11-kit/p11-kit-remote@.service
+/p11-kit/p11-kit-server.service
/p11-kit/virtual-fixed.c
/p11-kit/*.gnu.c
diff --git a/configure.ac b/configure.ac
index bd6ece0..a04ae43 100644
--- a/configure.ac
+++ b/configure.ac
@@ -545,6 +545,28 @@ AC_DEFINE_UNQUOTED(EXEEXT, ["$EXEEXT"], [File extension for executables])
privatedir='${libexecdir}/p11-kit'
AC_SUBST(privatedir)
+# --------------------------------------------------------------------
+# systemd
+
+AC_ARG_WITH([systemd],
+ AS_HELP_STRING([--without-systemd],
+ [Disable systemd socket activation]))
+
+AS_IF([test "$with_systemd" != "no"], [
+ PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], [],
+ [with_systemd=no])
+
+ PKG_CHECK_VAR([systemduserunitdir], [systemd], [systemduserunitdir], [],
+ [with_systemd=no])
+
+ AS_IF([test "$with_systemd" != "no"], [
+ with_systemd=yes
+ AC_DEFINE_UNQUOTED(WITH_SYSTEMD, 1, [Build with systemd socket activation])
+ ])
+])
+
+AM_CONDITIONAL(WITH_SYSTEMD, [test "$with_systemd" = "yes"])
+
AC_CONFIG_FILES([Makefile
doc/Makefile
doc/manual/Makefile
@@ -576,6 +598,7 @@ AC_MSG_NOTICE([build options:
With libtasn1 dependency: $with_libtasn1
With libffi: $with_libffi
With hash implementation: $with_hash_impl
+ With systemd: $with_systemd
Build trust module: $enable_trust_module
Trust module paths: $trust_status
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am
index 155ef3b..6b9a8a9 100644
--- a/p11-kit/Makefile.am
+++ b/p11-kit/Makefile.am
@@ -253,8 +253,30 @@ p11_kit_server_LDADD = \
libp11-tool.la \
libp11-common.la \
libp11-kit.la \
+ $(LIBSYSTEMD_LIBS) \
$(NULL)
+p11_kit_server_CFLAGS = \
+ $(COMMON_CFLAGS) \
+ $(LIBSYSTEMD_CFLAGS) \
+ $(NULL)
+
+if WITH_SYSTEMD
+p11-kit/p11-kit-server.service: p11-kit/p11-kit-server.service.in
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ sed 's|@bindir[@]|$(bindir)|g' $< > $@-t && \
+ mv -f $@-t $@
+
+CLEANFILES += p11-kit/p11-kit-server.service
+
+systemduserunit_DATA = \
+ p11-kit/p11-kit-server.socket \
+ p11-kit/p11-kit-server.service \
+ $(NULL)
+endif
+
+EXTRA_DIST += p11-kit/p11-kit-server.socket p11-kit/p11-kit-server.service.in
+
# Tests ----------------------------------------------------------------
p11_kit_LIBS = \
diff --git a/p11-kit/p11-kit-server.service.in b/p11-kit/p11-kit-server.service.in
new file mode 100644
index 0000000..975111e
--- /dev/null
+++ b/p11-kit/p11-kit-server.service.in
@@ -0,0 +1,15 @@
+[Unit]
+Description=p11-kit server
+Documentation=man:p11-kit(8)
+
+Requires=p11-kit-server.socket
+
+[Service]
+Type=simple
+StandardError=journal
+ExecStart=@bindir@/p11-kit server -f -n %t/p11-kit/pkcs11 pkcs11:
+Restart=on-failure
+
+[Install]
+Also=p11-kit-server.socket
+WantedBy=default.target
diff --git a/p11-kit/p11-kit-server.socket b/p11-kit/p11-kit-server.socket
new file mode 100644
index 0000000..31a3d4c
--- /dev/null
+++ b/p11-kit/p11-kit-server.socket
@@ -0,0 +1,11 @@
+[Unit]
+Description=p11-kit server
+
+[Socket]
+Priority=6
+Backlog=5
+ListenStream=%t/p11-kit/pkcs11
+SocketMode=0600
+
+[Install]
+WantedBy=sockets.target
diff --git a/p11-kit/server.c b/p11-kit/server.c
index e64890c..0c0092b 100644
--- a/p11-kit/server.c
+++ b/p11-kit/server.c
@@ -62,6 +62,10 @@
#include <sys/wait.h>
#include <unistd.h>
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
#ifdef HAVE_SIGHANDLER_T
#define SIGHANDLER_T sighandler_t
#elif HAVE_SIG_T
@@ -273,10 +277,16 @@ create_socket (const char *address,
umask (066);
rc = bind (sd, (struct sockaddr *)&sa, SUN_LEN (&sa));
if (rc == -1) {
- p11_message_err (errno, "could not create socket %s", socket_file);
+ p11_message_err (errno, "could not bind socket %s", socket_file);
return -1;
}
+ rc = listen (sd, 1024);
+ if (rc == -1) {
+ p11_message_err (errno, "could not listen to socket %s", socket_file);
+ return 1;
+ }
+
if (uid != -1 && gid != -1) {
rc = chown (socket_file, uid, gid);
if (rc == -1) {
@@ -356,7 +366,7 @@ server_loop (Server *server,
bool foreground,
struct timespec *timeout)
{
- int ret = 1, rc;
+ int ret;
int cfd;
pid_t pid;
socklen_t sa_len;
@@ -377,10 +387,6 @@ server_loop (Server *server,
ocsignal (SIGTERM, handle_term);
ocsignal (SIGINT, handle_term);
- server->socket = create_socket (server->socket_name, server->uid, server->gid);
- if (server->socket == -1)
- return 1;
-
/* run as daemon */
if (!foreground) {
pid = fork ();
@@ -403,10 +409,19 @@ server_loop (Server *server,
}
}
- rc = listen (server->socket, 1024);
- if (rc == -1) {
- p11_message_err (errno, "could not listen to socket %s", server->socket_name);
+#ifdef WITH_SYSTEMD
+ ret = sd_listen_fds (0);
+ if (ret > 1) {
+ p11_message ("too many file descriptors received");
return 1;
+ } else if (ret == 1) {
+ server->socket = SD_LISTEN_FDS_START + 0;
+ } else
+#endif
+ {
+ server->socket = create_socket (server->socket_name, server->uid, server->gid);
+ if (server->socket == -1)
+ return 1;
}
sigprocmask (SIG_BLOCK, &blockset, NULL);