#!/usr/bin/perl # Drakwizard # Copyright (C) 2002,2003 Mandrakesoft # # Authors: Arnaud Desmons # Florent Villard # antoine Giniès # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package MDK::Wizard::Samba; use strict; use common; use services; use MDK::Wizard::Wizcommon; use Data::Dumper; use Libconf qw(:functions); use Libconf::Templates; use Libconf::Glueconf::Samba::Smb_conf; my $wiz = new MDK::Wizard::Wizcommon; my $DOMAINNAME = chomp_(`dnsdomainname`); my $HOSTNAME = chomp_(`hostname`); my $o = { name => 'Samba wizard', var => { wiz_box_list => '', wiz_netbios => '', wiz_hosts_allow => '', wiz_do_file_sharing => '', wiz_all_printers => '', wiz_level => '', wiz_printers => '', wiz_do_printer_sharing => '', wiz_do_homes => '', wiz_workgroup => '', wiz_dir => '', wiz_share_comment => '', wiz_share_browseable => '', wiz_share_writable => '', wiz_banner => '', wiz_write_list => '', wiz_read_list => '', wiz_hosts_deny => '', wiz_log_file => '', wiz_log_level => '', wiz_max_log_size => '', list_printers => '', }, needed_rpm => [ 'samba-server' ], defaultimage => "/usr/share/wizards/samba_wizard/images/samba.png" }; # we ask glueconf to give us the structure representing /etc/samba/smb.conf my $samba = new Libconf::Glueconf::Samba::Smb_conf({ filename => '/etc/samba/smb.conf', }); #debug print Dumper($samba); my %level = ( 1 => N('All - No access restriction'), 2 => N('My rules - Ask me allowed and denied hosts') ); my @yesorno = qw(yes no); push @yesorno, ""; $o->{pages} = { welcome => { name => N('Samba Configuration Wizard') . "\n\n" . N('Samba allows your server to behave as a file and print server for workstations running non-Linux systems.') . "\n\n" . N('This wizard will help you configuring the Samba services of your server.'), no_back => 1, next => 'ask_workgroup' }, ask_workgroup => { name => N('Workgroup') . "\n\n" . N('Samba needs to know the Windows Workgroup it will serve.'), pre => sub { $o->{var}{wiz_workgroup} ||= $samba->{global}{workgroup}; $o->{var}{wiz_netbios} ||= $samba->{global}{netbios}; }, data => [ { label => N('Workgroup:'), val => \$o->{var}{wiz_workgroup} }, ], complete => sub { if (!$o->{var}{wiz_workgroup}) { $::in->ask_warn(N("Error"), N("The Workgroup is wrong.")); return 1 } else { return 0 }; }, next => 'ask_banner' }, ask_banner => { name => N('Server Banner.') . "\n\n" . N('The banner is the way this server will be described in the Windows workstations.'), pre => sub { $o->{var}{wiz_banner} ||= $samba->{global}{'server string'} }, data => [ { label => N('Banner:'), val => \$o->{var}{wiz_banner} }, ], complete => sub { if (!$o->{var}{wiz_banner}) { $::in->ask_warn(N("Error"), N("The Server Banner is incorrect.")); return 1 } else { return 0 }; }, next => 'ask_log' }, ask_log => { name => N('Samba Log') . "\n\n" . N(''), pre => sub { $o->{var}{wiz_log_file} ||= $samba->{global}{'log file'}; $o->{var}{wiz_log_level} ||= $samba->{global}{'log level'}; $o->{var}{wiz_max_log_size} ||= $samba->{global}{'max log size'}; }, data => [ { label => N('Log file:'), val => \$o->{var}{wiz_log_file} }, { label => N('Max log size:'), val => \$o->{var}{wiz_max_log_size} }, { label => N('Log level:'), val => \$o->{var}{wiz_log_level} }, ], next => 'ask_net', }, ask_net => { name => N('Access control') . "\n\n" . N('') . "\n\n" . N(''), pre => sub { $o->{var}{wiz_level} ||= 1 }, post => sub { return 'ask_netmask' if $o->{var}{wiz_level} == 2 }, data => [ { label => N('Access level :'), val => \$o->{var}{wiz_level}, list => [ keys %level ], format => sub { $level{$_[0]} } }, ], next => 'ask_services' }, ask_netmask => { name => N('Access control') . "\n\n" . N('* Example 1: allow all IPs in 150.203.*.*; except one\nhosts allow = 150.203. EXCEPT 150.203.6.66') . "\n\n" . N('* Example 2: allow hosts that match the given network/netmask\nhosts allow = 150.203.15.0/255.255.255.0') . "\n\n" . N('* Example 3: allow a couple of hosts\nhosts allow = lapland, arvidsjaur') . "\n\n" . N('* Example 4: allow only hosts in NIS netgroup "foonet", but deny access from one particular host\nhosts allow = @foonet\nhosts deny = pirate') . "\n\n" . N('Note that access still requires suitable user-level passwords.'), pre => sub { $o->{var}{wiz_hosts_allow} ||= $samba->{global}{'hosts allow'}; $o->{var}{wiz_hosts_allow} ||= $samba->{global}{'hosts deny'}; }, post => \&check, data => [ { label => N('Allow hosts:'), val => \$o->{var}{wiz_allow_host} }, { label => N('Deny hosts:'), val => \$o->{var}{wiz_deny_host} }, ], next => 'ask_services' }, ask_services => { name => N('Enabled Samba Services') . "\n\n" . N('Samba can provide a common file sharing area to your Windows workstation, and can also provide printer sharing for the printers connected to your server.'), pre => sub { $o->{var}{wiz_do_file_sharing} ||= exists $samba->{public}; $o->{var}{wiz_do_printer_sharing} ||= exists $samba->{printers}; $o->{var}{wiz_do_homes} ||= exists $samba->{homes}; }, data => [ { text => N('Enable file sharing area'), type => 'bool', val => \$o->{var}{wiz_do_file_sharing} }, { text => N('Enable Server Printer Sharing'), type => 'bool', val => \$o->{var}{wiz_do_printer_sharing} }, { text => N('Make home directories available for their owners'), type => 'bool', val => \$o->{var}{wiz_do_homes} }, ], complete => sub { if ($o->{var}{wiz_do_file_sharing} == 1) { return 'ask_dir'; } else { if ($o->{var}{wiz_do_printer_sharing}) { return 'ask_printers' } } }, next => 'ask_dir' }, warn_smbpasswd => { name => N('Warning.') . "\n\n" . N('You have selected to allow user access their home directories via samba but you/they must use smbpasswd to set a password.'), post => \&ask_dir, ignore => 1, next => 'summary' }, ask_dir => { name => N('Shared directory:') . "\n\n" . N('Type the path of the directory you want being shared.'), pre => sub { $o->{var}{wiz_dir} ||= $samba->{public}{path}; $o->{var}{wiz_share_comment} ||= $samba->{public}{comment}; $o->{var}{wiz_share_browseable} ||= $samba->{public}{browseable}; $o->{var}{wiz_share_writable} ||= $samba->{public}{writable}; }, data => [ { label => N('Comment:'), val => \$o->{var}{wiz_share_comment} }, { label => N('Shared directory:'), val => \$o->{var}{wiz_dir} }, { label => N('Browseable:'), val => \$o->{var}{wiz_share_browseable}, fixed_list => \@yesorno }, { label => N('Writable:'), val => \$o->{var}{wiz_share_writable}, fixed_list => \@yesorno }, { text => N("Create shared directory if it doesn't exist"), type => 'bool', val => \$o->{var}{create_missing_directory} }, ], post => sub { if (! -d $o->{var}{wiz_dir} and $o->{var}{create_missing_directory}) { wiz_mkdir_p($o->{var}{wiz_dir}) or $::in->ask_warn(N("Error"), N("Failed to create directory.")); return 1; } else { return 0 } }, next => 'ask_access' }, ask_access => { name => N('File permissions') . "\n\n" . N('Type users or group separated by a comma (groups must be preceded by a \'@\') like this :\nroot, fred, @users, @wheel for each kind of permission.') . "\n\n" . N(''), pre => sub { $o->{var}{wiz_read_list} ||= $samba->{public}{'read list'}; $o->{var}{wiz_write_list} ||= $samba->{public}{'write list'}; }, complete => sub { if ($o->{var}{wiz_do_printer_sharing}) { return 'ask_printers'; } else { return 'summary' } }, data => [ { label => N('read list:'), help => N('root, fred, @users, @wheel'), val => \$o->{var}{wiz_read_list} }, { label => N('write list:'), help => N('root, fred, @users, @wheel'), val => \$o->{var}{wiz_write_list} }, ], next => 'summary', }, ask_printers => { name => N('Select which printers you want to be accessible from known users'), pre => sub { $o->{var}{list_printers} ||= [ list_printers() ]; $o->{var}{wiz_box_list} ||= []; }, data => [ { text => N('Enable all printers'), type => 'bool', val => \$o->{var}{wiz_all_printers} }, { val => \$o->{var}{wiz_box_list}, boolean_list => \$o->{var}{list_printers}, disabled => sub { $o->{var}{wiz_all_printers} and return 1; 0 } }, ], next => 'summary' }, summary => { name => N('Configuring Samba') . "\n\n" . N('The wizard collected the following parameters configure Samba.') . "\n\n" . N('To accept these values, and configure your server, click the Next button or use the Back button to correct them.'), pre => sub { $o->{var}{printers} = get_printers(); $o->{var}{file_sharing} = $o->{var}{wiz_do_file_sharing} ? N("enabled") : N("disabled"); $o->{var}{printer_sharing} = $o->{var}{wiz_do_printer_sharing} ? N("enabled") : N("disabled"); $o->{var}{shared_homes} = $o->{var}{wiz_do_homes} ? N("enabled") : N("disabled") }, data => [ { label => N('Workgroup:'), fixed_val => \$o->{var}{wiz_workgroup} }, { label => N('Server Banner:'), fixed_val => \$o->{var}{wiz_banner} }, { label => N('File Sharing:'), fixed_val => \$o->{var}{file_sharing} }, { label => N('Shared directory:'), fixed_val => \$o->{var}{wiz_dir} }, { label => N('Print Server:'), fixed_val => \$o->{var}{printer_sharing} }, { label => N('Home:'), fixed_val => \$o->{var}{shared_homes} }, { label => N('Printers:'), fixed_val => \$o->{var}{printers} }, ], post => \&do_it, next => 'end' }, end => { name => N('Congratulations') . "\n\n" . N('The wizard successfully configured your Samba server.'), end => 1, next => 0 }, }; sub new { my ($class, $conf) = @_; bless { o => $o, }, $class; } sub wiz_mkdir_p { my ($dir) = @_; if (-d $dir) { # Do nothing, directory exists } elsif (-e $dir) { # Directory is file, we are not going to delete it return 0; } else { # Create parent directory wiz_mkdir_p(dirname($dir)) or return 0; # Create our directory mkdir($dir, 0755) or return 0; chown "nobody", "users", $dir; } 1; } sub check { $> and return 1; $wiz->{net}->is_dhcp() and return 2; 0; } sub check_services { $o->{var}{wiz_do_homes} and return 'warn_smbpasswd'; $o->{var}{wiz_do_file_sharing} and return 'ask_dir'; $o->{var}{wiz_do_printer_sharing} and return 'ask_printers'; } #section has the name of the printer sub add_printer { my ($printer) = @_; $samba->{$printer}{printer} = $printer; $samba->{$printer}{printable} = 'yes'; } sub remove_printer { my ($printer) = @_; delete $samba->{$printer}; } sub list_printers { my @list if 0; return @list if @list; @list = sort grep /^(?!\#).+/, map { my ($printer) = split(':', $_); } cat_("/etc/printcap"); if (@list) { @list } else { () } } sub printer_sharing { for (my $i; $i < @{$o->{var}{wiz_box_list}}; $i++) { my $printer = $o->{var}{list_printers}[$i]; if ($o->{var}{wiz_box_list}[$i]) { add_printer($printer); } else { remove_printer($printer); } } } sub get_printers { if ($o->{var}{wiz_do_printer_sharing}) { my $string; $o->{var}{wiz_all_printers} and return "all printers"; for (my $i; $i < @{$o->{var}{wiz_box_list}}; $i++) { $string .= "$o->{var}{list_printers}[$i]\n" if $o->{var}{wiz_box_list}[$i] } $string; } else { 'disabled'; } } sub ask_acces { 10; } sub ask_dir { return 'ask_dir' if $o->{var}{wiz_do_file_sharing}; return 'ask_printers' if $o->{var}{wiz_do_printer_sharing}; } # remember one variable cannot be commented and not in the same file. sub do_it { $::testing and return; # display a wait dialog box my $in = 'interactive'->vnew('su', 'Samba'); my $w = $in->wait_message(N("Samba server"), N("Configuring your Samba server...")); # global section $samba->{global}{workgroup} = $o->{var}{wiz_workgroup}; $samba->{global}{'server string'} = $o->{var}{wiz_banner}; if ($o->{var}{wiz_netbios}) { $samba->{global}{netbios} = $o->{var}{wiz_netbios}; } # log level in global section $samba->{global}{'log file'} = $o->{var}{wiz_log_file}; if ($o->{var}{wiz_log_level}) { $samba->{global}{'log level'} = $o->{var}{wiz_log_level}; } $samba->{global}{'max log size'} = $o->{var}{wiz_max_log_size}; # public share if ($o->{var}{wiz_do_file_sharing}) { $samba->{public}; if ($o->{var}{wiz_write_list}) { $samba->{public}{'write list'} = $o->{var}{wiz_write_list}; } if ($o->{var}{wiz_read_list}) { $samba->{public}{'read list'} = $o->{var}{wiz_read_list}; } # enable options if exist $o->{var}{wiz_share_comment} and $samba->{public}{comment} = $o->{var}{wiz_share_comment}; $o->{var}{wiz_share_browseable} and $samba->{public}{browseable} = $o->{var}{wiz_share_browseable}; $o->{var}{wiz_share_writable} and $samba->{public}{writable} = $o->{var}{wiz_share_writable}; standalone->explanations("Enabling $o->{var}{wiz_dir} samba file sharing"); $samba->{public}{path} = $o->{var}{wiz_dir}; } else { standalone->explanations("Disabling samba file sharing"); delete $samba->{public}; } # share home dir if ($o->{var}{wiz_do_homes}) { standalone->explanations("Enabling samba homes sharing"); $samba->{homes}; $samba->{homes}{comment} = "Home Directories"; $samba->{homes}{browseable} = "no"; $samba->{homes}{writable} = "yes"; $samba->{homes}{'create mode'} = "0700"; $samba->{homes}{''} = "0600"; } else { standalone->explanations("Disabling samba homes sharing"); delete $samba->{homes}; } standalone->explanations("Samba deny $o->{var}{wiz_hosts_deny}"); standalone->explanations("Samba allow $o->{var}{wiz_hosts_allow}"); # share printers if ($o->{var}{wiz_do_printer_sharing}) { standalone->explanations("Enabling printer sharing"); printer_sharing(); } else { standalone->explanations("Disabling printer sharing"); for(my $i; $i < @{$o->{var}{wiz_box_list}}; $i++) { remove_printer($o->{var}{list_printers}[$i]); } delete $samba->{printers}; } $samba->write_conf("/etc/samba/smb.conf"); if (services::is_service_running('smb')) { services::restart('smb') } else { services::start('smb') } undef $w; check_started('smbd'); } 1;