Skip to content

Commit

Permalink
#IP-1604 Fixed
Browse files Browse the repository at this point in the history
Changed: Usage for Apache2 mod_dbd to authenticate AWStats users
Removed: Support for AWStats static mode
[ci skip]
  • Loading branch information
nuxwin committed Aug 3, 2016
1 parent c10a573 commit acac836
Show file tree
Hide file tree
Showing 20 changed files with 288 additions and 891 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ LISTENERS
Fixed: Script for slave DNS provisionning won't work if HTML compression is disabled in panel

PACKAGES
Changed: Usage for Apache2 mod_dbd to authenticate AWStats users
Fixed: AWStats data can be accessed through localhost without any authentication
Fixed: AWStats (domains) configuration files are not generated (regression fix)
Fixed: Awstats package is never installed (regression fix)
Fixed: Could not authenticate to AWStats interface of domain aliases and subdomains
Removed: Support for AWStats static mode

PRESEED
Removed: SERVER_IPS parameter according changes made in installer
Expand Down Expand Up @@ -87,6 +89,7 @@ YOUTRACK
#IP-1595 courier-authdaemon service not started on reboot
#IP-1596 Previous DNS zone is not removed when changing BASE_SERVER_VHOST
#IP-1600 All domain names must be lowercased using mb_strtolower() PHP function
#IP-1604 Any customer can access AWStats interface of other customers

------------------------------------------------------------------------------------------------------------------------
1.3.0
Expand Down
2 changes: 1 addition & 1 deletion configs/debian/database/database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ INSERT IGNORE INTO `config` (`name`, `value`) VALUES
('PREVENT_EXTERNAL_LOGIN_ADMIN', '1'),
('PREVENT_EXTERNAL_LOGIN_RESELLER', '1'),
('PREVENT_EXTERNAL_LOGIN_CLIENT', '1'),
('DATABASE_REVISION', '240');
('DATABASE_REVISION', '241');

-- --------------------------------------------------------

Expand Down
2 changes: 0 additions & 2 deletions configs/debian/imscp.conf
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ WEBSTATS_PACKAGES =

## Awstats package specific variables

# could be 'dynamic' = 0 or 'static' = 1
AWSTATS_MODE =
AWSTATS_CACHE_DIR = /var/cache/awstats
AWSTATS_CONFIG_DIR = /etc/awstats
AWSTATS_ENGINE_DIR = /usr/lib/cgi-bin
Expand Down
9 changes: 3 additions & 6 deletions docs/1.3.x_errata.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@

### Pre-update tasks

Before running the i-MSCP installer for upgrading your installation to this new version, you must stop the `imscp_panel`
service manually.
Before running the i-MSCP installer, you must stop the `imscp_panel` service manually.

### AWStats authentication

Due to a security issue which has been fixed in that new version, it is no longer possible to setup arbitrary username
for authenticating to domains and subdomains AWStats interfaces. Right now it is mandatory to always use the customer
account name (which is the main domain name) to authenticate. However, you can still change the password for that user
through the protected area management interface.
Due to a security issue which has been fixed in that new version, the customers can now connect to AWStats interface
only by using their control panel login data.

### Database update

Expand Down
7 changes: 1 addition & 6 deletions docs/preseed.pl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# See documentation at http://wiki.i-mscp.net/doku.php?id=start:preseeding
#
# Author: Laurent Declercq <l.declercq@nuxwin.com>
# Last update: 2016.07.30
# Last update: 2016.08.03

%main::questions = (

Expand Down Expand Up @@ -279,11 +279,6 @@
# Possible values: Awstats, No
WEBSTATS_PACKAGES => 'Awstats',

# Awstats mode
# Only relevant if you use webstats Awstats package
# Possible values: 0 for dynamic, 1 for statis
AWSTATS_MODE => '0',

# FTP Web file manager packages
# Possible values: Pydio (only if PHP < 7.0), Net2ftp and MonstaFTP
FILEMANAGER_PACKAGE => 'MonstaFTP',
Expand Down
215 changes: 23 additions & 192 deletions engine/PerlLib/Package/Webstats/Awstats/Awstats.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package Package::Webstats::Awstats::Awstats;
use strict;
use warnings;
use Class::Autouse qw/ Package::Webstats::Awstats::Installer Package::Webstats::Awstats::Uninstaller /;
use iMSCP::Database;
use iMSCP::Debug;
use iMSCP::EventManager;
use iMSCP::Execute;
Expand Down Expand Up @@ -53,22 +54,6 @@ use parent 'Common::SingletonClass';
=over 4
=item showDialog(\%dialog)
Show dialog
Param iMSCP::Dialog \%dialog
Return int 0 or 30
=cut

sub showDialog
{
my ($self, $dialog) = @_;

Package::Webstats::Awstats::Installer->getInstance()->showDialog( $dialog );
}

=item install()
Process install tasks
Expand Down Expand Up @@ -118,7 +103,7 @@ sub setEnginePermissions

sub getDistroPackages
{
'awstats';
('awstats', 'libaprutil1-dbd-mysql');
}

=item addDmn(\%data)
Expand All @@ -135,59 +120,9 @@ sub addDmn
my ($self, $data) = @_;

my $rs = $self->_addAwstatsConfig( $data );
return $rs if $rs;

my $userStatisticsDir = "$data->{'HOME_DIR'}/statistics";

$rs = clearImmutable( $data->{'HOME_DIR'} );
return $rs if $rs;

if ($main::imscpConfig{'AWSTATS_MODE'} eq '1') {
# Static mode
unless (-d $userStatisticsDir) {
$rs = iMSCP::Dir->new( dirname => $userStatisticsDir )->make(
{ mode => 02750, user => $main::imscpConfig{'ROOT_USER'}, group => $data->{'GROUP'} }
);
return $rs if $rs;
} else {
$rs = setRights(
$userStatisticsDir,
{
user => $main::imscpConfig{'ROOT_USER'},
group => $data->{'GROUP'},
filemode => '0640',
recursive => 1
}
);
return $rs if $rs;
}

$rs = $self->_addAwstatsCronTask( $data );
return $rs if $rs;

unless (-f "$userStatisticsDir/awstats.$data->{'DOMAIN_NAME'}.html") {
$rs = execute(
"echo ".
"'perl ".
"$main::imscpConfig{'ENGINE_ROOT_DIR'}/PerlLib/Package/Webstats/Awstats/Scripts/awstats_buildstaticpages.pl ".
"-config=$data->{'DOMAIN_NAME'} ".
"-update -awstatsprog=$main::imscpConfig{'AWSTATS_ENGINE_DIR'}/awstats.pl -dir=$userStatisticsDir' ".
"| batch",
\ my $stdout,
\ my $stderr
);
debug( $stdout ) if $stdout;
error( $stderr ) if $stderr && $rs;
error( "Could not schedule generation of AWStats static pages" ) if $rs && !$stderr;
return $rs if $rs;
}
} else {
$rs = iMSCP::Dir->new( dirname => $userStatisticsDir )->remove();
return $rs if $rs;
}

$rs = setImmutable( $data->{'HOME_DIR'} ) if $data->{'WEB_FOLDER_PROTECTION'} eq 'yes';
$rs;
$rs ||= clearImmutable( $data->{'HOME_DIR'} );
$rs ||= iMSCP::Dir->new( dirname => "$data->{'HOME_DIR'}/statistics" )->remove(); # Transitional
$rs ||= setImmutable( $data->{'HOME_DIR'} ) if $data->{'WEB_FOLDER_PROTECTION'} eq 'yes';
}

=item deleteDmn(\%data)
Expand All @@ -211,33 +146,11 @@ sub deleteDmn
$rs ||= iMSCP::File->new( filename => $wrkFileName )->delFile() if -f $wrkFileName;
return $rs if $rs;

if ($main::imscpConfig{'AWSTATS_MODE'} eq '1') {
# Static mode
my $userStatisticsDir = "$data->{'HOME_DIR'}/statistics";

if (-d $userStatisticsDir) {
my @awstatsStaticFiles = iMSCP::Dir->new( dirname => $userStatisticsDir,
fileType =>
'^'.quotemeta( "awstats.$data->{'DOMAIN_NAME'}" ).'.*?\\.html'
)->getFiles();

if (@awstatsStaticFiles) {
my $file = iMSCP::File->new();
for(@awstatsStaticFiles) {
$file->{'filename'} = "$userStatisticsDir/$_";
$rs = $file->delFile();
return $rs if $rs;
}
}
}
}

my $awstatsCacheDir = $main::imscpConfig{'AWSTATS_CACHE_DIR'};

if (-d $awstatsCacheDir) {
my @awstatsCacheFiles = iMSCP::Dir->new( dirname => $awstatsCacheDir,
fileType =>
'^(?:awstats[0-9]+|dnscachelastupdate)'.quotemeta( ".$data->{'DOMAIN_NAME'}.txt" )
my @awstatsCacheFiles = iMSCP::Dir->new(
dirname => $awstatsCacheDir,
fileType => '^(?:awstats[0-9]+|dnscachelastupdate)'.quotemeta( ".$data->{'DOMAIN_NAME'}.txt" )
)->getFiles();

if (@awstatsCacheFiles) {
Expand All @@ -249,8 +162,6 @@ sub deleteDmn
}
}
}

$self->_deleteAwstatsCronTask( $data );
}

=item addSub(\%data)
Expand Down Expand Up @@ -317,7 +228,7 @@ sub _init
Add Apache configuration snippet for AWStats in the given domain vhost template file
Listener responsible to build and insert Apache configuration snipped for AWStats in the given domain vhost file. The
type of configuration snippet inserted depends on the AWStats mode (dynamic or static).
type of configuration snippet inserted depends on the AWStats mode (dynamic or static).
Param string \$cfgTpl Template file content
Param string $filename Template filename
Expand Down Expand Up @@ -345,19 +256,7 @@ sub _addAwstatsSection
"# SECTION addons END.\n",
$$cfgTpl
).
process(
{
AUTH_USER => $data->{'ROOT_DOMAIN_NAME'},
AUTHZ_ALLOW_ALL => version->parse( $httpdVersion ) >= version->parse( '2.4.0' )
? 'Require all granted' : 'Allow from all',
AWSTATS_WEB_DIR => $main::imscpConfig{'AWSTATS_WEB_DIR'},
DOMAIN_NAME => $data->{'DOMAIN_NAME'},
HOME_DIR => $data->{'HOME_DIR'},
HTACCESS_USERS_FILENAME => $httpd->{'config'}->{'HTACCESS_USERS_FILENAME'},
HTACCESS_GROUPS_FILENAME => $httpd->{'config'}->{'HTACCESS_GROUPS_FILENAME'}
},
$self->_getApacheConfSnippet()
).
process({ DOMAIN_NAME => $data->{'DOMAIN_NAME'} }, $self->_getApacheConfSnippet()).
" # SECTION addons END.\n",
$$cfgTpl
);
Expand All @@ -374,44 +273,12 @@ sub _addAwstatsSection

sub _getApacheConfSnippet
{
if ($main::imscpConfig{'AWSTATS_MODE'}) {
# static mode
<<EOF;
Alias /awstatsicons "{AWSTATS_WEB_DIR}/icon/"
Alias /stats "{HOME_DIR}/statistics/"
<Directory "{HOME_DIR}/statistics">
AllowOverride AuthConfig
DirectoryIndex awstats.{DOMAIN_NAME}.html
{AUTHZ_ALLOW_ALL}
</Directory>
<Location /stats>
AuthType Basic
AuthName "Statistics for domain {DOMAIN_NAME}"
AuthUserFile {HOME_DIR}/{HTACCESS_USERS_FILENAME}
AuthGroupFile {HOME_DIR}/{HTACCESS_GROUPS_FILENAME}
Require group statistics
</Location>
EOF
} else {
# Dynamic mode
<<EOF;
<<EOF;
ProxyRequests Off
ProxyPass /stats http://localhost/stats/{DOMAIN_NAME}
ProxyPassReverse /stats http://localhost/stats/{DOMAIN_NAME}
<Location /stats>
RewriteEngine on
RequestHeader set Proxy-User "{AUTH_USER}"
AuthType Basic
AuthName "Statistics for domain {DOMAIN_NAME}"
AuthUserFile {HOME_DIR}/{HTACCESS_USERS_FILENAME}
AuthGroupFile {HOME_DIR}/{HTACCESS_GROUPS_FILENAME}
Require group statistics
</Location>
ProxyErrorOverride On
EOF
}
}

=item _addAwstatsConfig(\%data)
Expand All @@ -434,10 +301,20 @@ sub _addAwstatsConfig
return 1;
}

my $qrs = iMSCP::Database->factory()->doQuery(
'admin_id', 'SELECT admin_id, admin_name FROM admin WHERE admin_id = ?', $data->{'DOMAIN_ADMIN_ID'}
);
unless (ref $qrs eq 'HASH') {
error($qrs);
return 1;
} elsif (!%{$qrs}) {
erro(sprintf('Could not retrieve data from admin whith ID %d', $data->{'DOMAIN_ADMIN_ID'})),
}

my $httpd = Servers::httpd->factory();
my $tags = {
ALIAS => $data->{'ALIAS'},
AUTH_USER => $data->{'ROOT_DOMAIN_NAME'},
AUTH_USER => "$qrs->{$data->{'DOMAIN_ADMIN_ID'}}->{'admin_name'}",
AWSTATS_CACHE_DIR => $main::imscpConfig{'AWSTATS_CACHE_DIR'},
AWSTATS_ENGINE_DIR => $main::imscpConfig{'AWSTATS_ENGINE_DIR'},
AWSTATS_WEB_DIR => $main::imscpConfig{'AWSTATS_WEB_DIR'},
Expand All @@ -461,52 +338,6 @@ sub _addAwstatsConfig
$rs ||= $file->owner( $main::imscpConfig{'ROOT_USER'}, $main::imscpConfig{'ROOT_GROUP'} );
}

=item _addAwstatsCronTask(\%data)
Add Awstats cron task
Param hash \%data Domain data
Return int 0 on success, other on failure
=cut

sub _addAwstatsCronTask
{
my ($self, $data) = @_;

Servers::cron->factory()->addTask( {
TASKID => "Package::Webstats::Awstats ($data->{'DOMAIN_NAME'})",
MINUTE => int( rand( 60 ) ), # random number between 0..59
HOUR => int( rand( 6 ) ), # random number between 0..5
DAY => '*',
MONTH => '*',
DWEEK => '*',
USER => $main::imscpConfig{'ROOT_USER'},
COMMAND =>
'nice -n 15 ionice -c2 -n5 perl '.
"$main::imscpConfig{'ENGINE_ROOT_DIR'}/PerlLib/Package/Webstats/Awstats/Scripts/awstats_buildstaticpages.pl ".
"-config=$data->{'DOMAIN_NAME'} -update ".
"-awstatsprog=$main::imscpConfig{'AWSTATS_ENGINE_DIR'}/awstats.pl ".
"-dir=$data->{'HOME_DIR'}/statistics > /dev/null 2>&1"
} );
}

=item _deleteAwstatsCronTask(\%data)
Remove AWStats cron task
Param hash \%data Domain data
Return int 0 on success, other on failure
=cut

sub _deleteAwstatsCronTask
{
my ($self, $data) = @_;

Servers::cron->factory()->deleteTask( { TASKID => "Addons::Webstats::Awstats ($data->{'DOMAIN_NAME'})" } );
}

=back
=head1 AUTHOR
Expand Down

0 comments on commit acac836

Please sign in to comment.