#!/usr/bin/perl # Drakwizard # Copyright (C) 2003 Mandrakesoft # # Author: Florent Villard # aginies # # 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::Proftpd; use strict; use common; use services; require MDK::Wizard::Wizcommon; my $wiz = MDK::Wizard::Wizcommon->new; my $o = { name => N("FTP wizard"), var => { wiz_ftp_external => '', # wiz_ftp_anon => '', # wiz_ftp_home => '', wiz_root_login => '', wiz_server_admin => '', wiz_default_root => '', wiz_ftp_resume => '', wiz_ftp_fxp => '', }, needed_rpm => [ 'proftpd', 'proftpd-anonymous' ], defaultimage => "$ENV{__WIZ_HOME__}ftp_wizard/images/FTP.png" }; my %opt = ( "SystemLog" => "/var/log/proftpd/proftpd.log", "TransferLog" => "/var/log/proftpd/xferlog", "Extendedlog" => "/var/log/proftpd/ftp.log", "LogFormat default" => qq("%h %l %u %t "%r" %s %b"), "LogFormat auth" => qq("%v [%P] %h %t "%r" %s"), "LogFormat write" => qq("%h %l %u %t "%r" %s %b"), "ServerIdent" => "off", "DeferWelcome" => "on", "DisplayConnect" => "/etc/banner-proftpd", "AccessDenyMsg" => qq(" !-!! ACCESS DENY !!-! SEEMS YOU HAVE NO RIGHT THERE !!"), "AccessGrantMsg" => qq(" -- Guest access granted for %u --"), "IdentLookups" => "off", "UseReverseDNS" => "off", "TimesGMT" => "off", "DirFakeUser" => "off nobody", "DirFakeGroup" => "off nobody", "DeleteAbortedStores" => "off", "PersistentPasswd" => "off", ); $o->{pages} = { welcome => { name => N("FTP Server Configuration Wizard") . "\n\n" . N("This wizard will help you configuring the FTP Server for your network."), no_back => 1, post => \&check, next => 'config' }, config => { name => N("FTP Server") . "\n\n" . N("Your server can act as an FTP Server toward your internal network (intranet) and as an FTP Server for the Internet.") . "\n\n" . N("Select the kind of FTP service you want to activate:") . "\n\n" . N("Don't check any box if you don't want to activate your FTP Server."), pre => sub { $o->{var}{wiz_ftp_internal} ||= 1; $o->{var}{wiz_ftp_external} ||= 0; }, data => [ { label => N("Enable the FTP Server for the Intranet"), type => 'bool', val => \$o->{var}{wiz_ftp_internal} }, { label => N("Enable the FTP Server for the Internet"), type => 'bool', val => \$o->{var}{wiz_ftp_external} }, ], next => 'options' }, options => { name => N("Ftp Proftpd server options") . "\n\n" . N("Permit root login: allow root to log on ftp server.") . "\n" . N("Admin Email: email address of FTP maintainer.") . "\n" . N("Chroot Home user: Block user in their home directory.") . "\n\n" . N("allow FTP resume: allow resume upload or download on ftp server.") . "\n" . N("Allow FXP: allow file transfert via other ftp."), pre => sub { $o->{var}{wiz_root_login} ||= 0; $o->{var}{wiz_default_root} ||= 1; $o->{var}{wiz_ftp_resume} ||= 1; $o->{var}{wiz_ftp_fxp} ||= 0; }, data => [ { label => N("Admin email"), val => \$o->{var}{wiz_server_admin} }, { label => N("Permit root Login"), type => 'bool', val => \$o->{var}{wiz_root_login} }, { label => N("Chroot Home user"), type => 'bool', val => \$o->{var}{wiz_default_root} }, { label => N("Allow FTP resume"), type => 'bool', val => \$o->{var}{wiz_ftp_resume} }, { label => N("Allow FXP"), type => 'bool', val => \$o->{var}{wiz_ftp_fxp} }, ], next => 'summary', }, warning_dhcp => { name => N("Warning.") . "\n\n" . N("Warning\nYou are in dhcp, server may not work with your configuration."), ignore => 1, next => 'config' }, must_be_root => { name => N("Error.") . "\n\n" . N("Sorry, you must be root to do this..."), ignore => 1, next => 'config' }, summary => { name => N("Configuring the FTP Server") . "\n\n" . N("The wizard collected the following parameters needed to configure your FTP Server") . "\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}{internal} = $o->{var}{wiz_ftp_internal} ? N("enabled") : N("disabled"); $o->{var}{external} = $o->{var}{wiz_ftp_external} ? N("enabled") : N("disabled"); $o->{var}{rootlogin} = $o->{var}{wiz_root_login} ? N("enabled") : N("disabled"); $o->{var}{defaultroot} = $o->{var}{wiz_default_root} ? N("enabled") : N("disabled"); $o->{var}{ftpresume} = $o->{var}{wiz_ftp_resume} ? N("enabled") : N("disabled"); $o->{var}{fxp} = $o->{var}{wiz_ftp_fxp} ? N("enabled") : N("disabled"); }, data => [ { label => N("Intranet FTP Server:"), fixed_val => \$o->{var}{internal} }, { label => N("Internet FTP Server:"), fixed_val => \$o->{var}{external} }, { label => N("Admin email"), fixed_val => \$o->{var}{wiz_server_admin} }, { label => N("Permit root Login"), fixed_val => \$o->{var}{rootlogin} }, { label => N("Chroot Home user"), fixed_val => \$o->{var}{defaultroot} }, { label => N("Allow FTP resume"), fixed_val => \$o->{var}{ftpresume} }, { label => N("Allow FXP"), fixed_val => \$o->{var}{fxp} }, ], post => \&do_it, next => 'end' }, end => { name => N("Congratulations") . "\n\n" . N("The wizard successfully configured your Intranet/Internet FTP Server"), end => 1, no_back => 1, next => 0 }, }; sub new { my ($class) = @_; bless { o => $o, }, $class; } sub true { my ($val) = @_; return member($val, qw(1 '1' "1" true 'true' "true")); } sub check_dir { -d $o->{var}{wiz_dir} and return 10; 1 } sub get_dir { my $file = "/etc/proftpd.conf"; die "no ftp configuration file found ! warning." if !-f $file; local *NEW; open(NEW, "< $file") or die "error while opening $file: $!"; local $_; while () { # we need 3 elements to consider section as known if (m/^\s*/s...m!^\s*!s) { if (m/^\s*/s) { return $1; } } } "" } sub check { $> and return 'must_be_root'; $wiz->{net}->is_dhcp and return 'warning_dhcp'; '' } sub print_anonymous { my ($arg) = @_; print ' # User ftp Group ftp UserAlias anonymous ftp MaxClients 10 DenyAll # '; } sub change_options { my ($var, $var_in_conf) = @_; my $file = "/etc/proftpd.conf"; my $status; if ($var == 1) { $status = "on" } else { $status = "off" } if (any { /^$var_in_conf/ } cat_($file)) { substInFile { s/$var_in_conf.*/$var_in_conf $status/ } $file; } else { append_to_file($file, "$var_in_conf $status\n") } } sub add_options { my ($var, $value) = @_; my $file = "/etc/proftpd.conf"; if (any { /^$var/ } cat_($file)) { substInFile { s/$var.*/$var $value/ } $file; } else { append_to_file($file, "$var $value\n") } } sub do_it { $::testing and return; my $wiz_ftp_internal = $o->{var}{wiz_ftp_external} ? 1 : true $o->{var}{wiz_ftp_internal}; my $wiz_ftp_external = true $o->{var}{wiz_ftp_external}; my $file = "/etc/proftpd.conf"; die "no ftp configuration file found ! warning." if !-f $file; MDK::Common::cp_af($file, $file . ".orig"); local *NEW; open(NEW, "< $file") or die "error while opening $file: $!"; my $allow = "all"; if ($wiz_ftp_internal && !$wiz_ftp_external) { ($allow) = $wiz->{net}->itf_get("IPADDR") =~ qr/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.)\d{1,3}$/; $allow .= " 127.0.0.1"; } elsif (!$wiz_ftp_external) { $allow = "none"; } $file = "/etc/proftpd.conf"; open(NEW, "< $file"); my $exist = 0; local $_; while () { # we need 3 elements to consider section as known if (m/^\s*/s...m!^\s*!s) { if (m/^\s*/s...m!^\s*!s) { if (/^\s*(?!#)\s*Order /) { $exist++; } if (/^\s*(?!#)\s*Allow /) { $exist++; } if (/^\s*(?!#)\s*Deny /) { $exist++; } } } } close(NEW); if ($exist < 3) { # Odd parameters are commented if exists to then add a known section substInFile { if (m/^\s*/s...m!^\s*!s) { if (m/^\s*/s...m!^\s*!s) { s/^\s*(?!#)\s*Order .*$/#$&\n/s; s/^\s*(?!#)\s*Allow .*$/#$&\n/s; s/^\s*(?!#)\s*Deny .*$/#$&\n/s; } } } $file; open(NEW, ">> $file"); print NEW ' # Order allow,deny Allow from '.$allow.' Deny from all # '; close NEW; } else { # the known section (3 parameters) is replaced with our needs substInFile { if (m/^\s*/s...m!^\s*!s) { if (m/^\s*/s...m!^\s*!s) { if (/^\s*(?!#)\s*Order /i) { if (!/\s*Order\s*allow,\s*deny\s*$/) { s//#$&\n Order allow,deny\n/; } } if (/^\s*(?!#)\s*Allow /i) { if (!/\s*Allow\s*from\s*$allow\s*$/) { s//#$&\n Allow from $allow/; } } if (/^\s*(?!#)\s*Deny /i) { if (!/\s*Deny\s*from\s*all\s*$/) { s//#$&\n Deny from all\n/; } } } } } $file; } # options # wiz_root_login wiz_server_admin wiz_default_root wiz_ftp_resume wiz_ftp_fxp if ($o->{var}{wiz_server_admin}) { if (any { /^ServerAdmin/ } cat_($file)) { substInFile { s/ServerAdmin.*/ServerAdmin $o->{var}{wiz_server_admin}/ } $file } else { append_to_file($file, "ServerAdmin $o->{var}{wiz_server_admin}") } } else { substInFile { s/ServerAdmin.*// } $file } change_options($o->{var}{wiz_root_login}, "RootLogin"); change_options($o->{var}{wiz_ftp_fxp}, "AllowForeignAddress"); # in ftp resume there is two options (store or retrieve) change_options($o->{var}{wiz_ftp_resume}, "AllowStoreRestart"); change_options($o->{var}{wiz_ftp_resume}, "AllowRetrieveRestart"); my $data; if ($o->{var}{wiz_default_root} == 1) { $data = "DefaultRoot ~" } else { $data = "" } if (any { /^DefaultRoot/ } cat_($file)) { substInFile { s/DefaultRoot.*/$data/ } $file; } else { append_to_file($file, "$data\n"); } my $cle, my $val; while (($cle, $val) = each %opt) { add_options($cle, $val); } if (services::is_service_running('proftpd')) { services::restart('proftpd') } else { services::start('proftpd') } } 1;