initial commit
This commit is contained in:
commit
f6021cecbb
6 changed files with 259 additions and 0 deletions
117
smtp_auth_sync.pl
Executable file
117
smtp_auth_sync.pl
Executable file
|
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
use Config;
|
||||
use IO::Socket;
|
||||
use IO::Select;
|
||||
use IPC::Open3;
|
||||
|
||||
# Configs
|
||||
# File to store the user:password hash mappings
|
||||
my $authfile = "/etc/mail/secrets";
|
||||
# UNIX Domain Socket inside the web chroot
|
||||
my $sfile = "/var/www/run/smtp_auth_sync.sock";
|
||||
# Absolute path of smtpctl
|
||||
my $smtpctl = "/usr/sbin/smtpctl";
|
||||
# Group OpenSMTPD runs with
|
||||
my $smtp_group = "_smtpd";
|
||||
# Group the webserver runs with
|
||||
my $www_group = "www";
|
||||
|
||||
sub read_timeout {
|
||||
my ($s, $conn) = @_;
|
||||
$s->can_read(2) or return 0;
|
||||
return readline($conn);
|
||||
}
|
||||
|
||||
my ($r_uid,$r_gid) = (getpwnam("root"))[2,3];
|
||||
my $s_gid = (getpwnam($smtp_group))[3] or die "group '$smtp_group' not found: $!";
|
||||
my $w_gid = (getpwnam($www_group))[3] or die "group '$www_group' not found: $!";
|
||||
my $authfiletmp = "${authfile}.tmp";
|
||||
|
||||
if ($Config{osname} eq "openbsd") {
|
||||
eval "use OpenBSD::Pledge";
|
||||
if ($Config{osvers} >= "6.6") {
|
||||
eval "use OpenBSD::Unveil";
|
||||
unveil($authfile, "rwc") or die "Unable to unveil: $!";
|
||||
unveil($authfiletmp, "rwc") or die "Unable to unveil: $!";
|
||||
unveil($sfile, "rwc") or die "Unable to unveil: $!";
|
||||
unveil($smtpctl, "rx") or die "Unable to unveil: $!";
|
||||
}
|
||||
pledge("rpath wpath cpath fattr chown unix proc exec prot_exec") or die "Unable to pledge: $!";
|
||||
}
|
||||
|
||||
if (-e $sfile) {
|
||||
unlink $sfile or die "Could not delete socket file '$sfile': $!";
|
||||
}
|
||||
my $sock = IO::Socket::UNIX->new(
|
||||
Type => SOCK_STREAM(),
|
||||
Local => $sfile,
|
||||
Listen => 1,
|
||||
) or die "Could not create socket: '$!'";
|
||||
chown($r_uid, $w_gid, $sfile);
|
||||
chmod(0620, $sfile);
|
||||
|
||||
sub cleanup {
|
||||
$sock->close();
|
||||
unlink $sfile;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
$SIG{INT} = \&cleanup;
|
||||
$SIG{TERM} = \&cleanup;
|
||||
|
||||
my $enc = "$smtpctl encrypt";
|
||||
my $update = "$smtpctl update table secrets";
|
||||
while (my $conn = $sock->accept()) {
|
||||
my $user;
|
||||
my $pass;
|
||||
my $s = IO::Select->new($conn);
|
||||
$user = read_timeout($s, $conn) or do { $conn->close(); next; };
|
||||
chomp($user);
|
||||
$pass = read_timeout($s, $conn) or do { $conn->close(); next; };
|
||||
chomp($pass);
|
||||
$conn->close();
|
||||
if ($user eq "" or $pass eq "") {
|
||||
next;
|
||||
}
|
||||
open3(\*WRITE, \*READ, 0, $enc);
|
||||
print WRITE "$pass";
|
||||
close(WRITE);
|
||||
chomp(my $hash = <READ>);
|
||||
close(READ);
|
||||
if ($hash eq "") {
|
||||
next;
|
||||
}
|
||||
if (! -f $authfile) {
|
||||
open(my $auth, ">", $authfile) or next;
|
||||
chown($r_uid, $s_gid, $authfile);
|
||||
chmod(0640, $authfile);
|
||||
print $auth "$user $hash\n";
|
||||
close($auth);
|
||||
next;
|
||||
}
|
||||
my $found = 0;
|
||||
open(my $auth, "<", $authfile) or do { print "Could not open file '$authfile': $!"; next; };
|
||||
chown($r_uid, $s_gid, $authfile);
|
||||
chmod(0640, $authfile);
|
||||
open(my $authtmp, ">", $authfiletmp) or do { print "Could not open file '$authfiletmp': $!"; next; };
|
||||
chown($r_uid, $s_gid, $authfiletmp);
|
||||
chmod(0640, $authfiletmp);
|
||||
while (<$auth>) {
|
||||
my $line = $_;
|
||||
if ($line =~ /$user/) {
|
||||
print $authtmp "$user $hash\n";
|
||||
$found = 1;
|
||||
} else {
|
||||
print $authtmp "$line";
|
||||
}
|
||||
}
|
||||
if ($found == 0) {
|
||||
print $authtmp "$user $hash\n";
|
||||
}
|
||||
close($auth);
|
||||
close($authtmp);
|
||||
rename($authfiletmp, $authfile);
|
||||
system("$update >/dev/null");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue