From 4ff037a6cce6fe760084c09bcfa92df03746d0c1 Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Wed, 4 Dec 2019 13:09:04 +0000 Subject: [PATCH] mumble: Add option to set SuperUser password Closes: #1680 Reviewed-by: James Valleroy --- actions/mumble | 79 +++++++++++++++++++++++++++++++ plinth/modules/mumble/__init__.py | 12 ----- plinth/modules/mumble/forms.py | 38 +++++++++++++++ plinth/modules/mumble/urls.py | 2 +- plinth/modules/mumble/views.py | 52 ++++++++++++++++++++ 5 files changed, 170 insertions(+), 13 deletions(-) create mode 100755 actions/mumble create mode 100644 plinth/modules/mumble/forms.py create mode 100644 plinth/modules/mumble/views.py diff --git a/actions/mumble b/actions/mumble new file mode 100755 index 000000000..6f0993a0c --- /dev/null +++ b/actions/mumble @@ -0,0 +1,79 @@ +#!/usr/bin/python3 + +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +""" +Configure Mumble server. +""" + +import argparse +import sys +from subprocess import Popen, PIPE + + +def parse_arguments(): + """Return parsed command line arguments as dictionary.""" + + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') + + subparsers.add_parser('create-password', + help='Setup mumble superuser password') + + return parser.parse_args() + + +def read_from_stdin(): + """Read password from stdin""" + + return (''.join(sys.stdin)).strip() + + +def subcommand_create_password(arguments): + """Save superuser password with murmurd command""" + + password = read_from_stdin() + + cmd = ['murmurd', '-ini', '/etc/mumble-server.ini', '-readsupw'] + proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False) + + # The exit code of the command above seems to be 1 when successful! + # checking if the 'phrase' is included in the error message which + # shows that the password is successfully set. + out, err = proc.communicate(input=password.encode()) + out, err = out.decode(), err.decode() + + phrase = "Superuser password set on server" + if phrase not in err: + print( + "Error occured while saving password: %s" % err + ) + sys.exit(1) + + +def main(): + """Parse arguments and perform all duties.""" + arguments = parse_arguments() + + subcommand = arguments.subcommand.replace('-', '_') + subcommand_method = globals()['subcommand_' + subcommand] + subcommand_method(arguments) + + +if __name__ == '__main__': + main() diff --git a/plinth/modules/mumble/__init__.py b/plinth/modules/mumble/__init__.py index 384c07236..565e6a478 100644 --- a/plinth/modules/mumble/__init__.py +++ b/plinth/modules/mumble/__init__.py @@ -26,7 +26,6 @@ from plinth import app as app_module from plinth import frontpage, menu from plinth.daemon import Daemon from plinth.modules.firewall.components import Firewall -from plinth.views import AppView from .manifest import backup, clients # noqa, pylint: disable=unused-import @@ -100,17 +99,6 @@ def init(): app.set_enabled(True) -class MumbleAppView(AppView): - app_id = 'mumble' - diagnostics_module_name = 'mumble' - name = name - description = description - clients = clients - manual_page = manual_page - port_forwarding_info = port_forwarding_info - icon_filename = icon_filename - - def setup(helper, old_version=None): """Install and configure the module.""" helper.install(managed_packages) diff --git a/plinth/modules/mumble/forms.py b/plinth/modules/mumble/forms.py new file mode 100644 index 000000000..14f387b89 --- /dev/null +++ b/plinth/modules/mumble/forms.py @@ -0,0 +1,38 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Mumble server configuration form +""" + +from django import forms +from django.utils.translation import ugettext_lazy as _ + +from plinth.forms import AppForm + + +class MumbleForm(AppForm): + """Mumble server configuration""" + super_user_password = forms.CharField( + max_length=20, + label=_('Set SuperUser Password'), + widget=forms.PasswordInput, + help_text=_( + 'Optional. Leave this field blank to keep the current password. ' + 'SuperUser password can be used to manage permissions in Mumble.' + ), + required=False, + ) diff --git a/plinth/modules/mumble/urls.py b/plinth/modules/mumble/urls.py index 78580d0b7..50cbde182 100644 --- a/plinth/modules/mumble/urls.py +++ b/plinth/modules/mumble/urls.py @@ -20,7 +20,7 @@ URLs for the Mumble module from django.conf.urls import url -from plinth.modules.mumble import MumbleAppView +from plinth.modules.mumble.views import MumbleAppView urlpatterns = [ url(r'^apps/mumble/$', MumbleAppView.as_view(), name='index'), diff --git a/plinth/modules/mumble/views.py b/plinth/modules/mumble/views.py new file mode 100644 index 000000000..65714a674 --- /dev/null +++ b/plinth/modules/mumble/views.py @@ -0,0 +1,52 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +from django.contrib import messages +from django.utils.translation import ugettext_lazy as _ + +from plinth import actions +from plinth.modules.mumble import ( + name, description, clients, manual_page, port_forwarding_info, +) +from plinth.modules.mumble.forms import MumbleForm +from plinth.views import AppView + + +class MumbleAppView(AppView): + app_id = 'mumble' + diagnostics_module_name = 'mumble' + name = name + description = description + clients = clients + manual_page = manual_page + port_forwarding_info = port_forwarding_info + form_class = MumbleForm + + def form_valid(self, form): + """Apply new superuser password if it exists""" + new_config = form.cleaned_data + + password = new_config.get('super_user_password') + if password: + actions.run_as_user( + 'mumble', ['create-password'], + input=password.encode(), + become_user="mumble-server", + ) + messages.success(self.request, + _('SuperUser password successfully updated.')) + + return super().form_valid(form)