[PATCH 1/3] daemons: review owner and permissions on PF_LOCAL sockets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Armin Schöffmann <armin.schoeffmann@xxxxxxxxxx>

Correctly set the desired owner (from config file) and permission
settings for PF_LOCAL sockets of kopano-{server, dagent, gateway,
ical, statsd, indexd}. This was inconsistently handled before and got
substantially broken by changes introduced with commit
kopanocore-8.7.81-162-g5995dbf7c [MERGE].

[Amendement: Services normally exposed via TCP/IP get to have
S_IxOTH, services normally only exposed via PF_LOCAL socket get not
to have S_IxOTH. —jengelh]

Fixes: kopanocore-8.7.81-146-g1dbcce2e3
References: KF-2512
---
 ECtools/idx_net.cpp                        |  3 ++-
 ECtools/statsd.cpp                         |  3 ++-
 caldav/CalDAV.cpp                          |  7 +++++--
 gateway/Gateway.cpp                        | 13 +++++++++----
 provider/server/ECSoapServerConnection.cpp | 15 ++++++++++-----
 spooler/DAgent.cpp                         |  3 ++-
 6 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/ECtools/idx_net.cpp b/ECtools/idx_net.cpp
index 246f34971..b624cd4a0 100644
--- a/ECtools/idx_net.cpp
+++ b/ECtools/idx_net.cpp
@@ -75,7 +75,8 @@ static int idx_listen(ECConfig *cfg, std::vector<struct pollfd> &pollers)
 	x.events = POLLIN;
 	pollers.reserve(idx_sock.size());
 	for (const auto &spec : idx_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &x.fd, S_IRUSR | S_IWUSR);
+		auto ret = ec_listen_generic(spec.c_str(), &x.fd, S_IRWUG,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0)
 			return ret;
 		pollers.push_back(x);
diff --git a/ECtools/statsd.cpp b/ECtools/statsd.cpp
index a49e8b312..27d058554 100644
--- a/ECtools/statsd.cpp
+++ b/ECtools/statsd.cpp
@@ -205,7 +205,8 @@ static HRESULT sd_listen(ECConfig *cfg, struct socks &sk)
 	memset(&pfd, 0, sizeof(pfd));
 	pfd.events = POLLIN;
 	for (const auto &spec : tokenize(cfg->GetSetting("statsd_listen"), ' ', true)) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0)
 			return MAPI_E_NETWORK_ERROR;
 		sk.pollfd.push_back(pfd);
diff --git a/caldav/CalDAV.cpp b/caldav/CalDAV.cpp
index 4f68c6dd4..007509877 100644
--- a/caldav/CalDAV.cpp
+++ b/caldav/CalDAV.cpp
@@ -28,6 +28,7 @@
 #include <iostream>
 #include <string>
 #include <getopt.h>
+#include <sys/stat.h>
 #include <kopano/ECConfig.h>
 #include <kopano/ECLogger.h>
 #include <kopano/ECChannel.h>
@@ -334,7 +335,8 @@ static HRESULT ical_listen(ECConfig *cfg)
 	memset(&pfd, 0, sizeof(pfd));
 	pfd.events = POLLIN;
 	for (const auto &spec : ical_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return MAPI_E_NETWORK_ERROR;
@@ -348,7 +350,8 @@ static HRESULT ical_listen(ECConfig *cfg)
 		g_socks.ssl.push_back(false);
 	}
 	for (const auto &spec : icals_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return MAPI_E_NETWORK_ERROR;
diff --git a/gateway/Gateway.cpp b/gateway/Gateway.cpp
index b44df3af6..2d6c0d9c7 100644
--- a/gateway/Gateway.cpp
+++ b/gateway/Gateway.cpp
@@ -16,6 +16,7 @@
 #include <netdb.h>
 #include <poll.h>
 #include <sys/resource.h>
+#include <sys/stat.h>
 #include <inetmapi/inetmapi.h>
 #include <mapi.h>
 #include <mapix.h>
@@ -471,7 +472,8 @@ static HRESULT gw_listen(ECConfig *cfg)
 	memset(&pfd, 0, sizeof(pfd));
 	pfd.events = POLLIN;
 	for (const auto &spec : pop3_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return MAPI_E_NETWORK_ERROR;
@@ -486,7 +488,8 @@ static HRESULT gw_listen(ECConfig *cfg)
 		g_socks.ssl.push_back(false);
 	}
 	for (const auto &spec : pop3s_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return MAPI_E_NETWORK_ERROR;
@@ -501,7 +504,8 @@ static HRESULT gw_listen(ECConfig *cfg)
 		g_socks.ssl.push_back(true);
 	}
 	for (const auto &spec : imap_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return MAPI_E_NETWORK_ERROR;
@@ -516,7 +520,8 @@ static HRESULT gw_listen(ECConfig *cfg)
 		g_socks.ssl.push_back(false);
 	}
 	for (const auto &spec : imaps_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd);
+		auto ret = ec_listen_generic(spec.c_str(), &pfd.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return MAPI_E_NETWORK_ERROR;
diff --git a/provider/server/ECSoapServerConnection.cpp b/provider/server/ECSoapServerConnection.cpp
index 3725bc690..78f480b2f 100644
--- a/provider/server/ECSoapServerConnection.cpp
+++ b/provider/server/ECSoapServerConnection.cpp
@@ -160,7 +160,8 @@ static int ignore_shutdown(struct soap *, SOAP_SOCKET, int shuttype)
 }
 
 static void custom_soap_bind(struct soap *soap, const char *bindspec,
-    bool v6only, int port)
+    bool v6only, int port = 0, int mode = -1, const char *user = nullptr,
+    const char *group = nullptr)
 {
 #if GSOAP_VERSION >= 20857
 	/* The v6only field exists in 2.8.56, but has no effect there. */
@@ -168,7 +169,7 @@ static void custom_soap_bind(struct soap *soap, const char *bindspec,
 #endif
 	soap->sndbuf = soap->rcvbuf = 0;
 	soap->bind_flags = SO_REUSEADDR;
-	auto ret = ec_listen_generic(bindspec, &soap->master);
+	auto ret = ec_listen_generic(bindspec, &soap->master, mode, user, group);
 	if (ret < 0) {
 		ec_log_crit("Unable to bind to %s: %s. Terminating.", bindspec,
 			soap->fault != nullptr ? soap->fault->faultstring : strerror(errno));
@@ -258,11 +259,15 @@ ECRESULT ECSoapServerConnection::ListenPipe(const char* lpPipeName, bool bPriori
 	std::unique_ptr<struct soap, ec_soap_deleter> lpsSoap(soap_new2(SOAP_IO_KEEPALIVE | SOAP_XML_TREE | SOAP_C_UTFSTRING, SOAP_IO_KEEPALIVE | SOAP_XML_TREE | SOAP_C_UTFSTRING));
 	if (lpsSoap == nullptr)
 		return KCERR_NOT_ENOUGH_MEMORY;
-	if (bPriority)
+	unsigned int mode = S_IRWUG;
+	if (bPriority) {
 		kopano_new_soap_listener(CONNECTION_TYPE_NAMED_PIPE_PRIORITY, lpsSoap.get());
-	else
+	} else {
 		kopano_new_soap_listener(CONNECTION_TYPE_NAMED_PIPE, lpsSoap.get());
-	custom_soap_bind(lpsSoap.get(), lpPipeName, false, 0);
+		mode |= S_IROTH | S_IWOTH;
+	}
+	custom_soap_bind(lpsSoap.get(), lpPipeName, false, 0, mode,
+		m_lpConfig->GetSetting("run_as_user"), m_lpConfig->GetSetting("run_as_group"));
 	/* Manually check for attachments, independent of streaming support. */
 	soap_post_check_mime_attachments(lpsSoap.get());
 	m_lpDispatcher->AddListenSocket(std::move(lpsSoap));
diff --git a/spooler/DAgent.cpp b/spooler/DAgent.cpp
index 6b21209aa..553a1d48b 100644
--- a/spooler/DAgent.cpp
+++ b/spooler/DAgent.cpp
@@ -2841,7 +2841,8 @@ static int dagent_listen(ECConfig *cfg, std::vector<struct pollfd> &pollers,
 	pollers.reserve(lmtp_sock.size());
 	closefd.reserve(lmtp_sock.size());
 	for (const auto &spec : lmtp_sock) {
-		auto ret = ec_listen_generic(spec.c_str(), &x.fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+		auto ret = ec_listen_generic(spec.c_str(), &x.fd, S_IRWUG | S_IROTH | S_IWOTH,
+		           cfg->GetSetting("run_as_user"), cfg->GetSetting("run_as_group"));
 		if (ret < 0) {
 			ec_log_err("Listening on %s failed: %s", spec.c_str(), strerror(-ret));
 			return ret;
-- 
2.21.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux