Commit 42e286e7 authored by Paul Cammish's avatar Paul Cammish
Browse files

Fixes for security and stats pages

parent be2b31cd
......@@ -63,7 +63,7 @@ module Symbiosis
# If no name is set, asssign a random new one.
#
if name.nil?
@name = random_string(10).downcase+".test"
@name = random_string(10).downcase+".test"
else
@name = name
end
......@@ -90,7 +90,7 @@ module Symbiosis
# If the directory exists, then check that we're not following a symlink.
#
if File.directory?(@directory)
directory_stat = File.stat(@directory)
#
......@@ -135,7 +135,7 @@ module Symbiosis
#
# Set the uid/gid for the domain.
#
@uid = directory_stat.uid
@uid = directory_stat.uid
@gid = directory_stat.gid
else
#
......@@ -146,8 +146,8 @@ module Symbiosis
prefix_stat = File.stat(@prefix)
if prefix_stat.uid < 1000
@uid = Etc.getpwnam("sympl").uid
@gid = Etc.getpwnam("sympl").gid
@uid = Etc.getpwnam("www-data").uid
@gid = Etc.getpwnam("www-data").gid
else
@uid = prefix_stat.uid
@gid = prefix_stat.gid
......@@ -163,10 +163,17 @@ module Symbiosis
end
@user = Etc.getpwuid(@uid).name
raise ArgumentError, "#{@directory} owned by a system user (UID less than 1000)" if @uid < 1000
if ( @uid < 1000 && @uid != 33 )
raise ArgumentError, "#{@directory} owned by a system user (UID less than 1000)"
end
@group = Etc.getgrgid(@gid).name
raise ArgumentError, "#{@directory} owned by a system group (GID less than 1000)" if @gid < 1000
if ( @gid < 1000 && @gid != 33 )
raise ArgumentError, "#{@directory} owned by a system group (GID less than 1000)"
end
end
#
......@@ -251,7 +258,7 @@ module Symbiosis
param = get_param("ip",self.config_dir)
@ip_addresses = []
if param.is_a?(String)
if param.is_a?(String)
param.split.each do |l|
begin
ip = IPAddr.new(l.strip)
......@@ -349,7 +356,7 @@ module Symbiosis
# Returns true or false.
#
def check_password(given_password, real_password)
#
#
# Make sure we have a real_password set, and chop whitespace of either end.
#
real_password = real_password.to_s.chomp.strip
......@@ -365,7 +372,7 @@ module Symbiosis
#
raise ArgumentError, "No password given" if given_password.empty?
#
#
# Check the password, crypt first, plaintext second.
#
if real_password =~ CRYPTED_PASSWORD_REGEXP
......@@ -407,7 +414,7 @@ module Symbiosis
#
# If our domain is real, see what symlinks are pointing at it.
#
if File.directory?(self.directory)
if File.directory?(self.directory)
self_stat = File.stat(self.directory)
......@@ -430,7 +437,7 @@ module Symbiosis
# Skip unless the target is a link (i.e. stat and lstat inodes differ)
# and the stat inode matches our own stat inode.
#
next unless target_lstat.ino != target_stat.ino and target_stat.ino == self_stat.ino
next unless target_lstat.ino != target_stat.ino and target_stat.ino == self_stat.ino
#
# Split
......@@ -440,8 +447,8 @@ module Symbiosis
#
# Don't want dotfiles.
#
next if this_domain =~ /^\./
next if this_domain =~ /^\./
#
# And record.
#
......@@ -490,7 +497,7 @@ module Symbiosis
#
# Returns the domain name as a string.
#
#
def to_s ; self.name.to_s ; end
end
end
......
......@@ -67,13 +67,30 @@ function secure_domain_dir()
fi
# Lock down the public/htdocs/logs directory, if it exists and contains webalizer html
# By default this is left unprotected, and includes IP addresses which are classified
# under GDPR as personally identifiable
if [ ! -f "${domain}/public/htdocs/stats/.htaccess" ]; then
if [ $( grep -c 'webalizer' "${domain}/public/htdocs/stats/index.html" 2> /dev/null ) != 0 ]; then
echo "# Prevent unauthorized access to stats
AuthType Basic
AuthName \"Access Restricted\"
AuthUserFile ${domain}/config/stats-htaccess
Require valid-user" > "${domain}/public/htdocs/stats/.htaccess"
fi
fi
# Enforce permissions for /srv/example.com/config - exim requires directory traversal (+x) as steps thorugh to the target.
if [ -d ${domain}/config ]; then
find "${domain}/config" \( -type f -o -type d \) \( ! -user sympl -o ! -group sympl \) ! -path '*ssl/sets*' -exec chown sympl:sympl {} \;
find "${domain}/config/ssl/sets" \( ! -user sympl -o ! -group ssl-cert \) -exec chown sympl:ssl-cert {} \;
if [ -d "${domain}/config/ssl/sets" ]; then
find "${domain}/config/ssl/sets" \( ! -user sympl -o ! -group ssl-cert \) -exec chown sympl:ssl-cert {} \;
fi
find "${domain}/config" \( -type f -a ! -perm 660 -exec chmod 660 {} \; \) -o \( -type d -a ! -perm 2771 -exec chmod 2771 {} \; \)
......
......@@ -42,6 +42,50 @@
#
# --manual, -m Show the manual for this script.
#
#!/usr/bin/ruby
#
# NAME
#
# sympl-web-configure - Auto-configure Apache2 sites with specified IPs
#
# SYNOPSIS
# sympl-web-configure [ --ssl-template | -s file ]
# [ --non-ssl-template | -t file ]
# [ --apache2-dir | -a directory ]
# [ --force | -f ] [ --no-reload | -n ]
# [ --help | -h ] [ --manual | -m ] [ --verbose | -v ] [domain domain ...]
#
# OPTIONS
#
# --ssl-template, -s file Specify the template file for SSL sites.
# Defaults to
# /etc/sympl/apache.d/non_ssl.template.erb
#
# --non-ssl-template, -t file Specify the template file for non-SSL sites.
# Defaults to
# /etc/sympl/apache.d/non_ssl.template.erb
#
# --apache2-dir, -a directory Specify the location of the Apache
# configuration directory. Defaults to
# /etc/apache2.
#
# --mass-ssl-template, -S file Specify the template file for mass-hosted SSL
# sites. Defaults to
# /etc/sympl/apache.d/zz-mass-hosting.ssl.template.erb
#
# --mass-non-ssl-template, -T file Specify the template file for mass-hosted
# non-SSL sites. Defaults to
# /etc/sympl/apache.d/zz-mass-hosting.template.erb
#
# --diff-only, -d Show the differences in the new configuration, without
# making any changes.
#
# --force, -f Force the re-creation of all sites.
#
# --no-reload, -n Do not reload Apache even if changes have taken place.
#
# --manual, -m Show the manual for this script.
#
# --help, -h Show brief usage instructions for this script.
#
# --verbose, -v Show debugging information.
......@@ -98,6 +142,7 @@
require 'getoptlong'
require 'fileutils'
#
# Entry point to the code
......@@ -228,7 +273,7 @@ require 'symbiosis/domain/http'
require 'symbiosis/config_files/apache'
#
# Set verbosity here to avoid warnings when using '--verbose' flag.
# Set verbosity here to avoid warnings when using '--verbose' flag.
#
$VERBOSELOCAL = verbosetmp
......@@ -291,6 +336,15 @@ domains.each do |domain|
next
end
# If the public directory exists, and the log directory doesn't
if File.directory?("#{domain.directory}/public/")
unless File.directory?("#{domain.directory}/public/logs")
verbose "\tCreating log directory #{publicdir}"
FileUtils.mkdir_p("#{domain.directory}/public/logs")
FileUtils.chown_R 'sympl', nil, "#{domain.directory}/public/logs", :verbose => false
end
end
if apache_mass_hosting_enabled and domain.ips.any?{|ip| primary_ips.include?(ip)}
if domain.ssl_enabled?
verbose "\tThis site has SSL enabled, and is using the host's primary IPs -- continuing with SNI."
......@@ -482,7 +536,7 @@ configurations.each do |config|
# the next domain.
#
if diff_only
# Disable $VERBOSELOCAL for config.diff call to avoid warnings.
# Disable $VERBOSELOCAL for config.diff call to avoid warnings.
$VERBOSELOCAL = false
puts config.diff(:color)
$VERBOSELOCAL = verbosetmp
......
......@@ -203,7 +203,7 @@ Symbiosis::Domains.each(prefix) do |domain|
#
# Make sure /srv/domain/config exists
#
Symbiosis::Utils.mkdir_p(domain.config_dir)
Symbiosis::Utils.mkdir_p(domain.config_dir)
#
# And write
......@@ -294,7 +294,7 @@ Symbiosis::Domains.each(prefix) do |domain|
#
# Now make sure that this directory is owned by the domain's owner.
#
unless File.stat(cdir).uid == domain.uid
unless File.stat(cdir).uid == domain.uid || File.stat(cdir).uid == 33
if File.symlink?(cdir)
verbose "\tSkipping as #{File.readlink(cdir)} (symlinked from #{cdir}) is not owned by #{domain.user}."
else
......@@ -327,4 +327,3 @@ Symbiosis::Domains.each(prefix) do |domain|
system( "cd #{domain.config_dir} && sudo -u '\##{domain.uid}' -- webalizer -c #{webalizer_conf} #{quiet} #{stinking_log_file}" )
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment