initial commit
This commit is contained in:
commit
f6021cecbb
6 changed files with 259 additions and 0 deletions
24
LICENSE
Normal file
24
LICENSE
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
Copyright (C) 2019 Marius Schellenberger
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* The names of the authors and/or contributors may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ston1th BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
65
README.md
Normal file
65
README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# SMTP Authentication Sync
|
||||
|
||||
This is a small daemon to sync Zarafa/Kopano users and passwords to an authentication file which can be used by OpenSMTPD.
|
||||
|
||||
Any successful login or password change will be synced to this file.
|
||||
The passwords are stored as Bcrypt hashes generated by `smtpctl encrypt`.
|
||||
|
||||
## Install
|
||||
|
||||
Copy `smtp_auth_sync.pl` to `/usr/local/sbin/smtp_auth_sync.pl` and set execute permissions:
|
||||
|
||||
`chmod 755 /usr/local/sbin/smtp_auth_sync.pl`
|
||||
|
||||
Use the `install_openbsd.sh` or `install_linux.sh` scripts to create the `rc` or `systemd` configs.
|
||||
|
||||
## Config Options
|
||||
|
||||
At the top of `smtp_auth_sync.pl` are some config options you may need to edit for your environment.
|
||||
|
||||
Defaults are for OpenBSD:
|
||||
|
||||
```
|
||||
# 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";
|
||||
```
|
||||
|
||||
## smtpd.conf
|
||||
|
||||
The table name must be `secrets`.
|
||||
|
||||
The file path can be changed.
|
||||
|
||||
```
|
||||
table secrets file:/etc/mail/secrets
|
||||
|
||||
listen on egress port 587 smtps pki mx.example.com auth <secrets>
|
||||
```
|
||||
|
||||
## Zarafa/Kopano Password Change Plugin
|
||||
|
||||
Plugin (version 1.3): https://github.com/silentsakky/zarafa-webapp-passwd
|
||||
|
||||
Apply this patch to send changed passwords to `smtp_auth_sync`:
|
||||
|
||||
Depending on your setup you may need to change `"/run/smtp_auth_sync.sock"` to the appropriate socket path inside your chroot.
|
||||
|
||||
```
|
||||
# Default path on OpenBSD
|
||||
cd /var/www/kopano-webapp/plugins/passwd/php
|
||||
|
||||
ftp -o class.passwdmodule.php.patch https://git.giftfish.de/ston1th/smtp_auth_sync/raw/branch/master/class.passwdmodule.php.patch
|
||||
|
||||
patch -p0 <class.passwdmodule.php.patch
|
||||
|
||||
rm class.passwdmodule.php.orig class.passwdmodule.php.patch
|
||||
```
|
||||
19
class.passwdmodule.php.patch
Normal file
19
class.passwdmodule.php.patch
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
--- class.passwdmodule.php 2019-09-08 16:43:34.699514994 +0200
|
||||
+++ class.passwdmodule.php 2019-09-08 16:44:07.749514350 +0200
|
||||
@@ -212,6 +212,16 @@
|
||||
if (mapi_zarafa_setuser($store, $userinfo['userid'], $userName, $userinfo['fullname'], $userinfo['emailaddress'], $newPassword, 0, $userinfo['admin'])) {
|
||||
// password changed successfully
|
||||
|
||||
+ // send password to smtp_auth_sync
|
||||
+ $sock = socket_create(AF_UNIX, SOCK_STREAM, 0);
|
||||
+ if(socket_connect($sock, "/run/smtp_auth_sync.sock")) {
|
||||
+ $send = $userName."\n";
|
||||
+ socket_send($sock, $send, strlen($send), 0);
|
||||
+ $send = $newPassword."\n";
|
||||
+ socket_send($sock, $send, strlen($send), 0);
|
||||
+ socket_close($sock);
|
||||
+ }
|
||||
+
|
||||
// send feedback to client
|
||||
$this->sendFeedback(true, array(
|
||||
'info' => array(
|
||||
17
install_linux.sh
Executable file
17
install_linux.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
cat <<EOF> /etc/systemd/system/smtp_auth_sync.service
|
||||
[Unit]
|
||||
Description=SMTP Authentication Sync
|
||||
After=syslog.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/sbin/smtp_auth_sync.pl
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable smtp_auth_sync
|
||||
systemctl start smtp_auth_sync
|
||||
17
install_openbsd.sh
Executable file
17
install_openbsd.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
|
||||
cat <<'EOF'> /etc/rc.d/smtp_auth_sync
|
||||
#!/bin/ksh
|
||||
|
||||
daemon="/usr/bin/perl"
|
||||
daemon_flags="/usr/local/sbin/smtp_auth_sync.pl"
|
||||
|
||||
. /etc/rc.d/rc.subr
|
||||
rc_bg=YES
|
||||
rc_reload=NO
|
||||
|
||||
rc_cmd $1
|
||||
EOF
|
||||
chmod 555 /etc/rc.d/smtp_auth_sync
|
||||
rcctl enable smtp_auth_sync
|
||||
rcctl start smtp_auth_sync
|
||||
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