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