samba: Users can enable a guest share

Related to  #1681

Signed-off-by: Veiko Aasa <veiko17@disroot.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Veiko Aasa 2019-11-10 21:08:44 +03:00 committed by James Valleroy
parent a8166bae7e
commit eaaa764387
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
6 changed files with 307 additions and 0 deletions

138
actions/samba Executable file
View File

@ -0,0 +1,138 @@
#!/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 <http://www.gnu.org/licenses/>.
#
"""
Configuration helper for samba.
"""
import argparse
import os
import shutil
import subprocess
import augeas
from plinth import action_utils
SHARES_PATH = '/var/lib/samba/shares'
DEFAULT_FILE = '/etc/default/samba'
CONF_PATH = '/etc/samba/smb-freedombox.conf'
CONF = r'''
#
# This file is managed and overwritten by Plinth. If you wish to manage
# Samba yourself, disable Samba in Plinth, remove this file and remove
# the --configfile parameter in /etc/default/samba
#
# To view configured samba shares use command `net conf list`
#
[global]
workgroup = WORKGROUP
log file = /var/log/samba/log.%m
max log size = 1000
logging = file
panic action = /usr/share/samba/panic-action %d
server role = standalone server
obey pam restrictions = yes
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
pam password change = yes
map to guest = bad user
# enable registry based shares
registry shares = yes
''' # noqa: E501
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('setup', help='Configure samba after install')
subparsers.required = True
return parser.parse_args()
def _share_conf(parameters, **kwargs):
"""Run samba registry edit command."""
subprocess.check_call(['net', 'conf'] + parameters, **kwargs)
def _create_open_share(name, path):
"""Create an open samba share."""
try:
_share_conf(['delshare', name], stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
pass
_share_conf(['addshare', name, path, 'writeable=y', 'guest_ok=y'])
_share_conf(['setparm', name, 'force group', 'sambashare'])
_share_conf(['setparm', name, 'inherit permissions', 'yes'])
def _use_config_file(conf):
"""Set samba configuration file location."""
aug = augeas.Augeas(
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE)
aug.load()
aug.set('/files' + DEFAULT_FILE + '/SMBDOPTIONS',
'--configfile={0}'.format(conf))
aug.save()
def subcommand_setup(_):
"""Configure samba after install."""
try:
os.mkdir(SHARES_PATH)
except FileExistsError:
pass
open_share_path = os.path.join(SHARES_PATH, 'open_share')
try:
os.mkdir(open_share_path)
except FileExistsError:
pass
# set folder group writable, 2 turns on the setGID bit
#
# TODO: some filesystems doesn't support chown and chmod
# (and it is not needed if mounted with correct parameters)
shutil.chown(open_share_path, group='sambashare')
os.chmod(open_share_path, 0o2775)
# use custom samba config file
with open(CONF_PATH, 'w') as file_handle:
file_handle.write(CONF)
_use_config_file(CONF_PATH)
_create_open_share('freedombox-open-share', open_share_path)
action_utils.service_restart('smbd')
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()

View File

@ -0,0 +1,113 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
"""
FreedomBox app to configure samba.
"""
import socket
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
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.utils import format_lazy
from .manifest import backup, clients # noqa, pylint: disable=unused-import
version = 1
managed_services = ['smbd']
managed_packages = ['samba']
name = _('Samba')
short_description = _('Samba File Sharing')
description = [
_('Samba file sharing allows to share files between computers in your '
'local network. '),
format_lazy(
_('If enabled, Samba share will be available at \\\\{hostname} on '
'Windows and smb://{hostname} on Linux and Mac'),
hostname=socket.gethostname()),
]
clients = clients
app = None
class SambaApp(app_module.App):
"""FreedomBox app for Samba file sharing."""
app_id = 'samba'
def __init__(self):
"""Create components for the app."""
super().__init__()
menu_item = menu.Menu('menu-samba', name, short_description, 'samba',
'samba:index', parent_url_name='apps')
self.add(menu_item)
shortcut = frontpage.Shortcut(
'shortcut-samba', name, short_description=short_description,
icon='samba', description=description,
configure_url=reverse_lazy('samba:index'), clients=clients,
login_required=True)
self.add(shortcut)
firewall = Firewall('firewall-samba', name, ports=['samba'])
self.add(firewall)
daemon = Daemon('daemon-samba', managed_services[0])
self.add(daemon)
def init():
"""Initialize the module."""
global app
app = SambaApp()
setup_helper = globals()['setup_helper']
if setup_helper.get_state() != 'needs-setup' and app.is_enabled():
app.set_enabled(True)
def setup(helper, old_version=None):
"""Install and configure the module."""
helper.install(managed_packages)
helper.call('post', actions.superuser_run, 'samba', ['setup'])
helper.call('post', app.enable)
def diagnose():
"""Run diagnostics and return the results."""
results = []
results.append(action_utils.diagnose_port_listening(137, 'udp4'))
results.append(action_utils.diagnose_port_listening(138, 'udp4'))
results.append(action_utils.diagnose_port_listening(139, 'tcp4'))
results.append(action_utils.diagnose_port_listening(139, 'tcp6'))
results.append(action_utils.diagnose_port_listening(445, 'tcp4'))
results.append(action_utils.diagnose_port_listening(445, 'tcp6'))
return results

View File

@ -0,0 +1 @@
plinth.modules.samba

View File

@ -0,0 +1,23 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from plinth.clients import validate
from plinth.modules.backups.api import validate as validate_backup
clients = validate([])
backup = validate_backup({})

View File

View File

@ -0,0 +1,32 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
"""
URLs for the Samba module.
"""
from django.conf.urls import url
from plinth.modules import samba
from plinth.views import AppView
urlpatterns = [
url(
r'^apps/samba/$',
AppView.as_view(app_id='samba', name=samba.name,
diagnostics_module_name='samba',
description=samba.description,
show_status_block=False), name='index')
]