From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 03F4E1FF396 for ; Wed, 22 May 2024 12:35:55 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 63D13A54E; Wed, 22 May 2024 12:36:12 +0200 (CEST) From: Maximiliano Sandoval To: pmg-devel@lists.proxmox.com Date: Wed, 22 May 2024 12:35:37 +0200 Message-Id: <20240522103537.274071-1-m.sandoval@proxmox.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.128 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment POISEN_SPAM_PILL 0.1 Meta: its spam POISEN_SPAM_PILL_1 0.1 random spam to be learned in bayes POISEN_SPAM_PILL_3 0.1 random spam to be learned in bayes SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [dbtools.pm, mailqueue.pm, multi-user.target, pmgpolicy.pid, report.pm, pmg-smtp-filter.pid, utils.pm, config.pm] Subject: [pmg-devel] [RFC PATCH] fix #4926: run pmg-smtp-filter and pmgpolicy without root rights X-BeenThere: pmg-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Mail Gateway development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pmg-devel-bounces@lists.proxmox.com Sender: "pmg-devel" New users 'pmg-smpt-filter' and 'pmgpolicy' are created for their respective processes. A shared group named 'pmg' is introduced for processes that need to be accessible from multiple processes like spamassassin, rrdcached or the /var/spool/pmg directory. We also create new users for the ruledb. Signed-off-by: Maximiliano Sandoval --- debian/pmg-smtp-filter.service | 5 ++- debian/pmgpolicy.service | 5 ++- debian/postinst | 64 ++++++++++++++++++++++++++++++++++ src/PMG/Config.pm | 12 +++---- src/PMG/DBTools.pm | 27 ++++++++++++-- src/PMG/MailQueue.pm | 7 ++-- src/PMG/Report.pm | 2 +- src/PMG/Utils.pm | 2 +- src/bin/pmg-smtp-filter | 8 ++--- src/bin/pmgpolicy | 8 ++--- 10 files changed, 117 insertions(+), 23 deletions(-) diff --git a/debian/pmg-smtp-filter.service b/debian/pmg-smtp-filter.service index cbf2d6f..aae07b7 100644 --- a/debian/pmg-smtp-filter.service +++ b/debian/pmg-smtp-filter.service @@ -11,10 +11,13 @@ ExecStart=/usr/bin/pmg-smtp-filter KillMode=mixed TimeoutStopSec=40 ExecReload=/bin/kill -HUP $MAINPID -PIDFile=/run/pmg-smtp-filter.pid +PIDFile=/run/pmg-smtp-filter/pmg-smtp-filter.pid Type=forking Restart=on-abort RestartSec=10 +User=pmg-smtp-filter +Group=pmg-smtp-filter +RuntimeDirectory=pmg-smtp-filter [Install] WantedBy=multi-user.target diff --git a/debian/pmgpolicy.service b/debian/pmgpolicy.service index 517a5d6..cebeac6 100644 --- a/debian/pmgpolicy.service +++ b/debian/pmgpolicy.service @@ -10,8 +10,11 @@ ExecStart=/usr/bin/pmgpolicy KillMode=mixed TimeoutStopSec=40 ExecReload=/bin/kill -HUP $MAINPID -PIDFile=/run/pmgpolicy.pid +PIDFile=/run/pmgpolicy/pmgpolicy.pid Type=forking +User=pmgpolicy +Group=pmgpolicy +RuntimeDirectory=pmgpolicy [Install] WantedBy=multi-user.target diff --git a/debian/postinst b/debian/postinst index 770c944..1308df0 100644 --- a/debian/postinst +++ b/debian/postinst @@ -48,6 +48,66 @@ migrate_apt_auth_conf() { fi } +migrate_pmg_smtp_filter() { + PMGPOLICY_USER="pmgpolicy" + PMG_SMTP_FILTER_USER="pmg-smtp-filter" + PMG_GROUP="pmg" + + # Add shared pmg group for usage together with rrdcached + if ! getent group | grep -q "^$PMG_GROUP:" ; then + echo -n "Adding group $PMG_GROUP.." + addgroup --quiet --system $PMG_GROUP 2>/dev/null ||true + echo "..done" + fi + + for user in $PMGPOLICY_USER $PMG_SMTP_FILTER_USER; do + if ! getent passwd | grep -q "^$user:"; then + echo -n "Adding system user $user.." + adduser --quiet \ + --system \ + --no-create-home \ + --disabled-password \ + --home /nonexistent \ + --group \ + $user 2>/dev/null || true + echo "..done" + fi + + if ! getent group $PMG_GROUP | grep -q "$user"; then + echo -n "Adding user $user to $PMG_GROUP group.." + adduser --quiet $user $PMG_GROUP 2>/dev/null ||true + echo "..done" + fi + + if ! getent group systemd-journal | grep -q $user ; then + echo -n "Adding user $user to systemd-journal group.." + adduser --quiet $user systemd-journal 2>/dev/null ||true + echo "..done" + fi + done + + chown :pmg /var/spool/pmg/active + chown :pmg /var/spool/pmg/virus + chown :pmg /var/spool/pmg/spam + chown :pmg /var/spool/pmg/attachment + chmod g+w /var/spool/pmg/active + chmod g+w /var/spool/pmg/virus + chmod g+w /var/spool/pmg/spam + chmod g+w /var/spool/pmg/attachment + + chown :pmg /var/lib/pmg + + # FIXME: This is not ideal + if ! cat /etc/default/rrdcached | grep -q "^SOCKGROUP=pmg$"; then + sed -i "s/#SOCKGROUP=root/SOCKGROUP=pmg/" /etc/default/rrdcached + if systemctl --quiet is-active rrdcached.service ; then + deb-systemd-invoke reload-or-try-restart rrdcached.service >/dev/null || true + fi + fi + + pmgdb update >/dev/null 2>&1 & +} + case "$1" in triggered) @@ -67,6 +127,10 @@ case "$1" in if test ! -e /proxmox_install_mode ; then + if test -n "$2" && dpkg --compare-versions "$2" 'lt' '8.1.3'; then + migrate_pmg_smtp_filter + fi + pmgconf="/etc/pmg/pmg.conf" if test -n "$2" && dpkg --compare-versions "$2" 'lt' '8.0.2'; then # on upgrade add pre 8.0 default values for advfilter, use_awl and use_bayes diff --git a/src/PMG/Config.pm b/src/PMG/Config.pm index a0daba3..a91bb10 100644 --- a/src/PMG/Config.pm +++ b/src/PMG/Config.pm @@ -1594,13 +1594,13 @@ sub rewrite_config_spam { # delete AW and bayes databases if those features are disabled if (!$use_awl) { - $changes = 1 if unlink '/root/.spamassassin/auto-whitelist'; + $changes = 1 if unlink '/var/lib/pmg/spamassassin/auto-whitelist'; } if (!$use_bayes) { - $changes = 1 if unlink '/root/.spamassassin/bayes_journal'; - $changes = 1 if unlink '/root/.spamassassin/bayes_seen'; - $changes = 1 if unlink '/root/.spamassassin/bayes_toks'; + $changes = 1 if unlink '/var/lib/pmg/spamassassin/bayes_journal'; + $changes = 1 if unlink '/var/lib/pmg/spamassassin/bayes_seen'; + $changes = 1 if unlink '/var/lib/pmg/spamassassin/bayes_toks'; } # make sure we have the custom SA files (else cluster sync fails) @@ -1819,8 +1819,8 @@ my $pmg_service_params = { }, }; -my $smtp_filter_cfg = '/run/pmg-smtp-filter.cfg'; -my $smtp_filter_cfg_lock = '/run/pmg-smtp-filter.cfg.lck'; +my $smtp_filter_cfg = '/run/pmg-smtp-filter/pmg-smtp-filter.cfg'; +my $smtp_filter_cfg_lock = '/run/pmg-smtp-filter/pmg-smtp-filter.cfg.lck'; sub dump_smtp_filter_config { my ($self) = @_; diff --git a/src/PMG/DBTools.pm b/src/PMG/DBTools.pm index 8770d06..96bac00 100644 --- a/src/PMG/DBTools.pm +++ b/src/PMG/DBTools.pm @@ -38,7 +38,7 @@ sub cgreylist_merge_sql { } sub open_ruledb { - my ($database, $host, $port) = @_; + my ($database, $host, $port, $user) = @_; $port //= 5432; @@ -74,13 +74,20 @@ sub open_ruledb { return $rdb; } else { my $dsn = "DBI:Pg:dbname=$database;host=/var/run/postgresql;port=$port"; - my $user = $> == 0 ? 'root' : 'www-data'; + $user //= $> == 0 ? 'root' : 'www-data'; my $dbh = DBI->connect($dsn, $user, undef, { PrintError => 0, RaiseError => 1 }); return $dbh; } } +sub open_ruledb_as { + my ($database, $user) = @_; + + open_ruledb($database, undef, undef, $user); +} + + sub delete_ruledb { my ($dbname) = @_; @@ -609,6 +616,22 @@ sub upgradedb { } } + foreach my $user ("pmgpolicy", "pmg-smtp-filter") { + eval { + my $silent_opts = { outfunc => sub {}, errfunc => sub {} }; + postgres_admin_cmd('createuser', $silent_opts, '-D', $user); + + $dbh->begin_work; + $dbh->do("GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO \"$user\""); + $dbh->do("GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO \"$user\""); + $dbh->commit; + + }; + if (my $err = $@) { + $dbh->rollback; + } + } + foreach my $table (keys %$tables) { eval { $dbh->do("ANALYZE $table"); }; warn $@ if $@; diff --git a/src/PMG/MailQueue.pm b/src/PMG/MailQueue.pm index 4e37cb9..adbf28c 100644 --- a/src/PMG/MailQueue.pm +++ b/src/PMG/MailQueue.pm @@ -33,12 +33,13 @@ sub create_spooldirs { "$spooldir/attachment", ]) if $cleanup; - mkpath([ + mkpath( "$spooldir/active", "$spooldir/spam", "$spooldir/virus", "$spooldir/attachment", - ]); + { group=>'pmg', chmod=>0775 }, + ); if ($lcid) { mkpath "$spooldir/cluster/$lcid/virus"; @@ -68,7 +69,7 @@ sub new_fileid { my $uid; my $subsubdir = ''; - if (!($fh = IO::File->new ($path, 'w+', 0600))) { + if (!($fh = IO::File->new ($path, 'w+', 0660))) { die "unable to create file '$path': $! : ERROR"; } diff --git a/src/PMG/Report.pm b/src/PMG/Report.pm index 100a197..3512ecf 100644 --- a/src/PMG/Report.pm +++ b/src/PMG/Report.pm @@ -123,7 +123,7 @@ sub check_dns_resolution { debug => 0, local_tests_only => 0, home_dir_for_helpers => '/root', - userstate_dir => '/root/.spamassassin', + userstate_dir => '/var/lib/pmg/spamassassin', dont_copy_prefs => 1, stop_at_threshold => 0, }); diff --git a/src/PMG/Utils.pm b/src/PMG/Utils.pm index 5d9ded4..09cb42d 100644 --- a/src/PMG/Utils.pm +++ b/src/PMG/Utils.pm @@ -1462,7 +1462,7 @@ sub get_pg_server_version { sub reload_smtp_filter { - my $pid_file = '/run/pmg-smtp-filter.pid'; + my $pid_file = '/run/pmg-smtp-filter/pmg-smtp-filter.pid'; my $pid = PVE::Tools::file_read_firstline($pid_file); return 0 if !$pid; diff --git a/src/bin/pmg-smtp-filter b/src/bin/pmg-smtp-filter index 6061459..4a6a643 100755 --- a/src/bin/pmg-smtp-filter +++ b/src/bin/pmg-smtp-filter @@ -80,7 +80,7 @@ if (!GetOptions( exit (-1); } -$opt_pidfile = "/run/${prog_name}.pid" if !$opt_pidfile; +$opt_pidfile = "/run/pmg-smtp-filter/${prog_name}.pid" if !$opt_pidfile; my $max_servers = 1; my $min_servers = 1; @@ -387,7 +387,7 @@ sub load_config { PMG::MailQueue::create_spooldirs($self->{cinfo}->{local}->{cid}); eval { - my $dbh = PMG::DBTools::open_ruledb ($database); + my $dbh = PMG::DBTools::open_ruledb_as($database, 'pmg-smtp-filter'); $self->{ruledb} = PMG::RuleDB->new ($dbh); # load rulecache @@ -460,7 +460,7 @@ sub pre_loop_hook { debug => 0, local_tests_only => $opt_testmode || !$rbl_checks, home_dir_for_helpers => '/root', - userstate_dir => '/root/.spamassassin', + userstate_dir => "/var/lib/pmg/spamassassin", dont_copy_prefs => 1, stop_at_threshold => 0, }); @@ -538,7 +538,7 @@ sub run_dequeue { my $cinfo = PVE::INotify::read_file("cluster.conf"); - my $dbh = eval { PMG::DBTools::open_ruledb($database) }; + my $dbh = eval { PMG::DBTools::open_ruledb_as($database, 'pmg-smtp-filter') }; if ($err = $@) { $self->log (0, "ERROR: $err"); return; diff --git a/src/bin/pmgpolicy b/src/bin/pmgpolicy index df2e66f..5e5c69e 100755 --- a/src/bin/pmgpolicy +++ b/src/bin/pmgpolicy @@ -56,7 +56,7 @@ if (!GetOptions(%_opts)) { exit (-1); } -$opt_pidfile = "/run/pmgpolicy.pid" if !$opt_pidfile; +$opt_pidfile = "/run/pmgpolicy/pmgpolicy.pid" if !$opt_pidfile; $opt_max_dequeue = 0 if $opt_testmode; initlog('pmgpolicy', 'mail'); @@ -142,7 +142,7 @@ sub run_dequeue { my $dbh; eval { - $dbh = PMG::DBTools::open_ruledb($database); + $dbh = PMG::DBTools::open_ruledb_as($database, 'pmgpolicy'); }; my $err = $@; @@ -343,7 +343,7 @@ sub load_config { my $dbh; eval { - $dbh = PMG::DBTools::open_ruledb($database); + $dbh = PMG::DBTools::open_ruledb_as($database, 'pmgpolicy'); $self->{ruledb} = PMG::RuleDB->new($dbh); $self->{rulecache} = PMG::RuleCache->new($self->{ruledb}); }; @@ -523,7 +523,7 @@ sub greylist_value { $self->log(0, 'Database connection broken - trying to reconnect'); my $dbh; eval { - $dbh = PMG::DBTools::open_ruledb($database); + $dbh = PMG::DBTools::open_ruledb_as($database, 'pmgpolicy'); }; my $err = $@; if ($err) { -- 2.39.2 _______________________________________________ pmg-devel mailing list pmg-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel