diff --git a/doc/user.xml b/doc/user.xml
index 85f060a0b..f6c08948b 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -1158,6 +1158,11 @@ systemctl start mpd.socket
+
+ local_permissions may be used to assign
+ other permissions to clients connecting on a local socket.
+
+
password allows the client to send a
password to gain other permissions. This option may be
diff --git a/src/Permission.cxx b/src/Permission.cxx
index a3d98a0de..8387b3754 100644
--- a/src/Permission.cxx
+++ b/src/Permission.cxx
@@ -49,6 +49,10 @@ static std::map permission_passwords;
static unsigned permission_default;
+#ifdef HAVE_UN
+static unsigned local_permissions;
+#endif
+
static unsigned
ParsePermission(const char *p)
{
@@ -121,6 +125,14 @@ void initPermissions(void)
if (param)
permission_default = parsePermissions(param->value.c_str());
+
+#ifdef HAVE_UN
+ param = config_get_param(ConfigOption::LOCAL_PERMISSIONS);
+ if (param != nullptr)
+ local_permissions = parsePermissions(param->value.c_str());
+ else
+ local_permissions = permission_default;
+#endif
}
int getPermissionFromPassword(char const* password, unsigned* permission)
@@ -137,3 +149,13 @@ unsigned getDefaultPermissions(void)
{
return permission_default;
}
+
+#ifdef HAVE_UN
+
+unsigned
+GetLocalPermissions() noexcept
+{
+ return local_permissions;
+}
+
+#endif
diff --git a/src/Permission.hxx b/src/Permission.hxx
index 782632644..e0009471e 100644
--- a/src/Permission.hxx
+++ b/src/Permission.hxx
@@ -20,6 +20,8 @@
#ifndef MPD_PERMISSION_HXX
#define MPD_PERMISSION_HXX
+#include "check.h"
+
static constexpr unsigned PERMISSION_NONE = 0;
static constexpr unsigned PERMISSION_READ = 1;
static constexpr unsigned PERMISSION_ADD = 2;
@@ -31,6 +33,11 @@ int getPermissionFromPassword(char const* password, unsigned* permission);
unsigned
getDefaultPermissions();
+#ifdef HAVE_UN
+unsigned
+GetLocalPermissions() noexcept;
+#endif
+
void
initPermissions();
diff --git a/src/client/Listener.cxx b/src/client/Listener.cxx
index 663fd9a7b..a607379b8 100644
--- a/src/client/Listener.cxx
+++ b/src/client/Listener.cxx
@@ -24,11 +24,27 @@
#include "net/UniqueSocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
+static unsigned
+GetPermissions(SocketAddress address, int uid) noexcept
+{
+ (void)uid; // TODO: implement option to derive permissions from uid
+
+#ifdef HAVE_UN
+ if (address.GetFamily() == AF_LOCAL)
+ return GetLocalPermissions();
+#else
+ (void)address;
+#endif
+
+ return getDefaultPermissions();
+}
+
void
ClientListener::OnAccept(UniqueSocketDescriptor fd,
SocketAddress address, int uid) noexcept
{
+
client_new(GetEventLoop(), partition,
std::move(fd), address, uid,
- getDefaultPermissions());
+ GetPermissions(address, uid));
}
diff --git a/src/config/ConfigOption.hxx b/src/config/ConfigOption.hxx
index 697909593..6a66fff39 100644
--- a/src/config/ConfigOption.hxx
+++ b/src/config/ConfigOption.hxx
@@ -48,6 +48,7 @@ enum class ConfigOption {
ZEROCONF_NAME,
ZEROCONF_ENABLED,
PASSWORD,
+ LOCAL_PERMISSIONS,
DEFAULT_PERMS,
AUDIO_OUTPUT_FORMAT,
MIXER_TYPE,
diff --git a/src/config/ConfigTemplates.cxx b/src/config/ConfigTemplates.cxx
index 683e30ccd..8a0438340 100644
--- a/src/config/ConfigTemplates.cxx
+++ b/src/config/ConfigTemplates.cxx
@@ -43,6 +43,7 @@ const ConfigTemplate config_param_templates[] = {
{ "zeroconf_name" },
{ "zeroconf_enabled" },
{ "password", true },
+ { "local_permissions" },
{ "default_permissions" },
{ "audio_output_format" },
{ "mixer_type" },