in spamd-apache2/lib/Mail/SpamAssassin/Spamd/Config.pm [167:320]
sub _validate {
my ($self) = @_;
# sanity checking on parameters: if --socketpath is used, it means that we're
# using UNIX domain sockets, none of the IP params are allowed. The code would
# probably work ok if we didn't check it, but it's better if we detect the
# error and report it lest the admin find surprises.
if (exists $self->{'socketpath'}) {
die "ERROR: --socketpath mutually exclusive with"
. " --allowed-ips/--ssl/--auth-ident/--port params"
if exists $self->{'allowed-ips'} && @{ $self->{'allowed-ips'} } > 0
|| exists $self->{'ssl'}
|| exists $self->{'auth-ident'}
|| exists $self->{'port'};
}
else {
die "ERROR: --socketowner/group/mode requires --socketpath param"
if exists $self->{'socketowner'}
|| exists $self->{'socketgroup'}
|| exists $self->{'socketmode'};
# These can be changed on command line with -A flag,
# but only if we're not using UNIX domain sockets
# warning: no validation here
$self->{'allowed-ips'} =
exists $self->{'allowed-ips'} && @{ $self->{'allowed-ips'} }
? [map { split /,/, $_; } @{ $self->{'allowed-ips'} }]
: ['127.0.0.1'];
$self->{'listen-ip'} =
!exists $self->{'listen-ip'}
? ['127.0.0.1']
: defined $self->{'listen-ip'} && grep(length, @{ $self->{'listen-ip'} })
? [grep length, map { split /,/, $_; } @{ $self->{'listen-ip'} }]
: undef; # handle !defined elsewhere
}
# bug 2228: make the values of (almost) all parameters which accept file paths
# absolute, so they are still valid after daemonize()
for my $opt (
grep(exists $self->{$_},
qw(configpath siteconfigpath socketpath pidfile server-cert server-key
PREFIX DEF_RULES_DIR LOCAL_RULES_DIR LOCAL_STATE_DIR)),
grep { exists $self->{$_} && $self->{$_} }
qw(home_dir_for_helpers) # value is optional
)
{
$self->{$opt} = Mail::SpamAssassin::Util::untaint_file_path(
File::Spec->rel2abs($self->{$opt}) # rel2abs taints the new value!
);
}
# -d
for my $opt (
grep(exists $self->{$_},
qw(configpath siteconfigpath
PREFIX DEF_RULES_DIR LOCAL_RULES_DIR LOCAL_STATE_DIR)),
grep { exists $self->{$_} && $self->{$_} }
qw(home_dir_for_helpers) # value is optional
)
{
die "ERROR: --$opt='$self->{$opt}' does not exist or not a directory\n"
unless -d $self->{$opt};
}
# >= 0
for my $opt (grep exists $self->{$_}, qw(min-spare max-spare)) {
die "ERROR: --$opt must be >= 0\n" if $self->{$opt} <= 0;
}
# >= 1
for my $opt (
grep exists $self->{$_},
qw(timeout-tcp timeout-child min-children max-children max-conn-per-child)
)
{
next if $self->{$opt} >= 1;
warn "ERROR: --$opt must be >= 1, ignoring\n"; # die?
delete $self->{$opt};
}
# ident-based spamc user authentication
if ($self->{'auth-ident'}) {
eval { sub Net::Ident::_export_hooks(); require Net::Ident };
die "spamd: ident-based authentication requested,",
" but Net::Ident is unavailable\n"
if $@;
if (exists $self->{'ident-timeout'} && $self->{'ident-timeout'} <= 0) {
die "ERROR: --ident-timeout must be > 0\n";
}
##Net::Ident->import(qw(ident_lookup));
}
# let's not modify %ENV here...
my $home =
(exists $ENV{HOME} && defined $ENV{HOME} && -d $ENV{HOME})
? $ENV{HOME}
: undef;
if (exists $self->{username})
{ # spamd is going to run as another user, so reset $HOME
if (my $nh = (getpwnam($self->{username}))[7]) {
$home = $nh;
}
else {
die "spamd: unable to determine home directory for user"
. " '$self->{username}'\n";
}
}
if (!exists $self->{home_dir_for_helpers}) {
die "ERROR: \$HOME='$home' does not exist or not a directory\n"
unless defined $home && -d $home;
$self->{home_dir_for_helpers} = $home;
}
if (exists $self->{'max-spare'}) {
if (exists $self->{'min-spare'}) {
## emulate Apache behaviour:
## http://httpd.apache.org/docs-2.0/mod/prefork.html#maxspareservers
$self->{'max-spare'} = $self->{'min-spare'} + 1
if $self->{'max-spare'} < $self->{'min-spare'};
}
else {
$self->{'min-spare'} = $self->{'max-spare'};
}
}
elsif (exists $self->{'min-spare'}) {
$self->{'max-spare'} = $self->{'min-spare'};
}
# set other defaults
for my $opt (keys %defaults) {
$self->{$opt} = $defaults{$opt} if !exists $self->{$opt};
}
# check for server certs, must be done after setting other defaults
if ($self->{'ssl'}) {
$self->{'server-key'} ||= "$self->{LOCAL_RULES_DIR}/certs/server-key.pem";
$self->{'server-cert'} ||= "$self->{LOCAL_RULES_DIR}/certs/server-cert.pem";
eval { require IO::Socket::SSL };
die "spamd: SSL encryption requested, but IO::Socket::SSL is unavailable\n"
if $@;
die "spamd: server key file '$self->{'server-key'}' does not exist\n"
unless -f $self->{'server-key'};
die "spamd: server certificate file '$self->{'server-cert'}' does not exist\n"
unless -f $self->{'server-cert'};
}
# XXX: delete LOCAL_{RULES,STATE}_DIR and PREFIX if eq $defaults{$_}?
1;
}