Skip to content

Instantly share code, notes, and snippets.

@victorlclopes
Last active October 16, 2020 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save victorlclopes/f5aa081f1a9c76466aaf3f3dc5bd60b7 to your computer and use it in GitHub Desktop.
Save victorlclopes/f5aa081f1a9c76466aaf3f3dc5bd60b7 to your computer and use it in GitHub Desktop.
Assign certificates to your MailCleaner installation and restart the necessary services. Written by Graham Barnett.
#!/usr/bin/perl -w
#
# Mailcleaner - SMTP Antivirus/Antispam Gateway
# Copyright (C) 2020 Graham Barnett
#
# 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 of the License, 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
#
#
# This script update the ssl and tls certificates in the config database.
#
# Usage:
# set_certificates.pl
# Note: to access mysql, use /opt/mysql5/bin/mysql -S /var/mailcleaner/run/mysql_master/mysqld.sock -p mc_config
use strict;
if ($0 =~ m/(\S*)\/\S+.pl$/) {
my $path = $1."/../../lib";
unshift (@INC, $path);
}
use DBI();
use Getopt::Long;
sub usage() {
print STDERR << "EOF";
usage: $0
--set_web : set cert for web
--set_mta_in : set cert for mta inbound
--set_mta_filter : set cert for mta filtering
--set_mta_out : set cert for mta outbound
--row_set_id : the set_if of the row to set - defaults to 1
--enable_tls_mta : enable tls for mta - defaults to true
--key : filename of cert key
--data : filename of cert data
--chain : filename of cert chain for web
--help : display usage
EOF
exit;
}
my $set_web;
my $set_mta_in;
my $set_mta_filter;
my $set_mta_out;
my $help = 0;
my $row_set_id = 1;
my $enable_tls_mta = 1;
my $cert_key_fname;
my $cert_data_fname;
my $cert_chain_fname;
GetOptions(\my %OPT, 'set_web!' => \$set_web, 'set_mta_in!' => \$set_mta_in, 'set_mta_filter!' => \$set_mta_filter, 'set_mta_out!' => \$set_mta_out, 'row_set_id=i' => \$row_set_id, 'enable_tls_mta!' => \$enable_tls_mta, 'key=s' => \$cert_key_fname, 'data=s' => \$cert_data_fname, 'chain=s' => \$cert_chain_fname, 'help!' => \$help )
or usage();
if ($help) {
usage();
}
if (!$set_web && !$set_mta_in && !$set_mta_filter && !$set_mta_out) {
print STDERR "Specify set_web, set_mta_in, set_mta_filter or set_mta_out\n";
usage();
}
if (!$cert_key_fname || !$cert_data_fname || !$cert_chain_fname) {
print STDERR "Specify key, data, chain\n";
usage();
}
open(my $cert_key_fh, "<:encoding(utf8)", $cert_key_fname) or die "Could not open certificate key file '$cert_key_fname'. $!";
my @tls_cert_key = <$cert_key_fh>;
chomp @tls_cert_key;
close $cert_key_fh;
open(my $cert_data_fh, "<:encoding(utf8)", $cert_data_fname) or die "Could not open certificate data file '$cert_data_fname'. $!";
my @tls_cert_data = <$cert_data_fh>;
chomp @tls_cert_data;
close $cert_data_fh;
open(my $cert_chain_fh, "<:encoding(utf8)", $cert_chain_fname) or die "Could not open certificate chain file '$cert_chain_fname'. $!";
my @tls_cert_chain = <$cert_chain_fh>;
chomp @tls_cert_chain;
close $cert_chain_fh;
my $DEBUG = 1;
my %config = readConfig("/etc/mailcleaner.conf");
my $HOSTID=$config{HOSTID};
my $lasterror = "";
my $dbh;
$dbh = DBI->connect("DBI:mysql:database=mc_config;host=localhost;mysql_socket=$config{VARDIR}/run/mysql_master/mysqld.sock",
"mailcleaner", "$config{MYMAILCLEANERPWD}", {RaiseError => 0, PrintError => 0})
or fatal_error("CANNOTCONNECTDB", $dbh->errstr);
#############################
sub set_https_certificate
{
my $set_id = $_[0];
my $tls_cert_key = $_[1];
my $tls_cert_data = $_[2];
my $tls_cert_chain = $_[3];
my $upd_mta = $dbh->prepare("UPDATE httpd_config SET tls_certificate_key=?,tls_certificate_data=?,tls_certificate_chain=? WHERE set_id=? AND (tls_certificate_key<>? OR tls_certificate_data<>? OR tls_certificate_chain<>?)");
$upd_mta->bind_param(1, $tls_cert_key);
$upd_mta->bind_param(2, $tls_cert_data);
$upd_mta->bind_param(3, $tls_cert_chain);
$upd_mta->bind_param(4, $set_id);
$upd_mta->bind_param(5, $tls_cert_key);
$upd_mta->bind_param(6, $tls_cert_data);
$upd_mta->bind_param(7, $tls_cert_chain);
my $rows = $upd_mta->execute;
if ($rows == "0E0") {
return 0;
}
if (!$rows) {
if ($dbh->errstr) {
die "Couldn't update config: " . $dbh->errstr;
}
else {
die "Couldn't update config - reason unknown";
}
}
return 1;
}
#############################
sub set_mta_certificate
{
my $stage = $_[0];
my $set_id = $_[1];
my $enable_tls = $_[2];
my $tls_cert_key = $_[3];
my $tls_cert_data = $_[4];
my $upd_mta = $dbh->prepare("UPDATE mta_config SET use_incoming_tls=?,tls_certificate_key=?,tls_certificate_data=? WHERE set_id=? and stage=? and (use_incoming_tls<>? OR tls_certificate_key<>? OR tls_certificate_data<>?)");
$upd_mta->bind_param(1, $enable_tls);
$upd_mta->bind_param(2, $tls_cert_key);
$upd_mta->bind_param(3, $tls_cert_data);
$upd_mta->bind_param(4, $set_id);
$upd_mta->bind_param(5, $stage);
$upd_mta->bind_param(6, $enable_tls);
$upd_mta->bind_param(7, $tls_cert_key);
$upd_mta->bind_param(8, $tls_cert_data);
my $rows = $upd_mta->execute;
if ($rows == "0E0") {
return 0;
}
if (!$rows) {
if ($dbh->errstr) {
die "Couldn't update config: " . $dbh->errstr;
}
else {
die "Couldn't update config - reason unknown";
}
}
return 1;
}
####################################################################################
sub readConfig { # Reads configuration file given as argument.
my $configfile = shift;
my %config;
my ($var, $value);
open CONFIG, $configfile or die "Cannot open $configfile: $!\n";
while (<CONFIG>) {
chomp; # no newline
s/#.*$//; # no comments
s/^\*.*$//; # no comments
s/;.*$//; # no comments
s/^\s+//; # no leading white
s/\s+$//; # no trailing white
next unless length; # anything left?
my ($var, $value) = split(/\s*=\s*/, $_, 2);
$config{$var} = $value;
}
close CONFIG;
return %config;
}
######################################################################################
if ($set_web) {
if (set_https_certificate($row_set_id, (join "\n", @tls_cert_key), (join "\n", @tls_cert_data), (join "\n", @tls_cert_chain, 1))) {
system("/usr/mailcleaner/etc/init.d/apache restart");
}
}
if ($set_mta_in) {
if (set_mta_certificate(1, $row_set_id, $enable_tls_mta, (join "\n", @tls_cert_key), (join "\n", @tls_cert_data) . "\n" . (join "\n", @tls_cert_chain), 1)) {
system("/usr/mailcleaner/etc/init.d/exim_stage1 restart");
}
}
if ($set_mta_filter) {
if (set_mta_certificate(2, $row_set_id, $enable_tls_mta, (join "\n", @tls_cert_key), (join "\n", @tls_cert_data) . "\n" . (join "\n", @tls_cert_chain), 1)) {
system("/usr/mailcleaner/etc/init.d/exim_stage2 restart");
}
}
if ($set_mta_out) {
if (set_mta_certificate(4, $row_set_id, $enable_tls_mta, (join "\n", @tls_cert_key), (join "\n", @tls_cert_data) . "\n" . (join "\n", @tls_cert_chain), 1)) {
system("/usr/mailcleaner/etc/init.d/exim_stage4 restart");
}
}
$dbh->disconnect();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment