From f25286a60b8ad26994c5c88c60b7c0ec998ae803 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 26 Jan 2016 18:12:37 +0000 Subject: first commit, it works already --- lib/Config/ClawsMail/Account.pm | 80 ++++++++++++++++++++++++++++ lib/Config/ClawsMail/Password.pm | 110 +++++++++++++++++++++++++++++++++++++++ lib/Config/ClawsMail/Server.pm | 29 +++++++++++ 3 files changed, 219 insertions(+) create mode 100644 lib/Config/ClawsMail/Account.pm create mode 100644 lib/Config/ClawsMail/Password.pm create mode 100644 lib/Config/ClawsMail/Server.pm (limited to 'lib/Config/ClawsMail') diff --git a/lib/Config/ClawsMail/Account.pm b/lib/Config/ClawsMail/Account.pm new file mode 100644 index 0000000..c00bad4 --- /dev/null +++ b/lib/Config/ClawsMail/Account.pm @@ -0,0 +1,80 @@ +package Config::ClawsMail::Account; +use Moo; +use 5.020; +use Types::Standard qw(Str InstanceOf); +use Config::ClawsMail::Server; +use namespace::clean; + +has [qw(account_name name address)] => ( + is => 'ro', + required => 1, + isa => Str, +); + +has [qw(imap smtp)] => ( + is => 'ro', + isa => InstanceOf['Config::ClawsMail::Server'], +); + +my @ssl_string=qw(no ssl starttls); +sub new_from_config { + my ($class,$config) = @_; + die "unhandled protocol" unless $config->{protocol} eq '3'; + + my $imap_server = Config::ClawsMail::Server->new({ + host => $config->{receive_server}, + port => ( + $config->{set_imapport} + ? $config->{imap_port} + : $config->{ssl_imap} == 1 + ? scalar getservbyname('imaps','tcp') + : scalar getservbyname('imap','tcp') + ), + ssl => $ssl_string[$config->{ssl_imap}], + %{$config}{qw(user_id password)}, + }); + + my $smtp_server = Config::ClawsMail::Server->new({ + host => $config->{smtp_server}||$config->{receive_server}, + port => ( + $config->{set_smtpport} + ? $config->{smtp_port} + : $config->{ssl_smtp} == 1 + ? scalar getservbyname('smtps','tcp') + : scalar getservbyname('smtp','tcp') + ), + ssl => $ssl_string[$config->{ssl_smtp}], + ( $config->{use_smtp_auth} ? ( + user_id => $config->{smtp_user_id} || $config->{user_id}, + password => ( + $config->{smtp_password} eq '!' + ? $config->{password} + : $config->{smtp_password} + ), + ) : () ), + }); + + return $class->new({ + %{$config}{qw(account_name name address)}, + imap => $imap_server, + smtp => $smtp_server, + }); +} + +sub email_transport { + my ($self) = @_; + + require Email::Sender::Transport::SMTPS; + my $smtp = $self->smtp; + return Email::Sender::Transport::SMTPS->new( + host => $smtp->host, + port => $smtp->port, + ssl => $smtp->ssl, + ( $smtp->user_id ? ( + sasl_username => $smtp->user_id, + sasl_password => $smtp->cleartext_password, + ) : () ) + ); +} + +1; diff --git a/lib/Config/ClawsMail/Password.pm b/lib/Config/ClawsMail/Password.pm new file mode 100644 index 0000000..c3e1b19 --- /dev/null +++ b/lib/Config/ClawsMail/Password.pm @@ -0,0 +1,110 @@ +package Config::ClawsMail::Password; +use strict; +use warnings; +use Inline 'C'; +use MIME::Base64; +use namespace::clean -except => [qw(decrypt_password)]; + +sub cleartext_password { + my ($password) = @_; + return decrypt_password(decode_base64($password)); +} + +1; + +__DATA__ +__C__ +#include + +#define PASSCRYPT_KEY "passkey0" +unsigned char crypt_cfb_iv[64]; +int crypt_cfb_blocksize = 8; /* 8 for DES */ + +static void crypt_unpack(unsigned char *a) { + int i, j; + + for (i = 7; i >= 0; --i) + for (j = 7; j >= 0; --j) + a[(i << 3) + j] = (a[i] & (0x80 >> j)) != 0; +} + +static void crypt_cfb_xor( + unsigned char *to, + const unsigned char *from, + unsigned len) { + unsigned i; + unsigned j; + unsigned char c; + + for (i = 0; i < len; i++) { + c = 0; + for (j = 0; j < 8; j++) + c = (c << 1) | *from++; + *to++ ^= c; + } +} + +static void crypt_cfb_shift( + unsigned char *to, + const unsigned char *from, + unsigned len) { + unsigned i; + unsigned j; + unsigned k; + + if (len < crypt_cfb_blocksize) { + i = len * 8; + j = crypt_cfb_blocksize * 8; + for (k = i; k < j; k++) { + to[0] = to[i]; + ++to; + } + } + + for (i = 0; i < len; i++) { + j = *from++; + for (k = 0x80; k; k >>= 1) + *to++ = ((j & k) != 0); + } +} + +static void crypt_cfb_buf( + const char key[8], + unsigned char *buf, + unsigned len, + unsigned chunksize, + int decrypt) { + unsigned char temp[64]; + + memcpy(temp, key, 8); + crypt_unpack(temp); + setkey((const char *) temp); + memset(temp, 0, sizeof(temp)); + + memset(crypt_cfb_iv, 0, sizeof(crypt_cfb_iv)); + + if (chunksize > crypt_cfb_blocksize) + chunksize = crypt_cfb_blocksize; + + while (len) { + memcpy(temp, crypt_cfb_iv, sizeof(temp)); + encrypt((char *) temp, 0); + if (chunksize > len) + chunksize = len; + if (decrypt) + crypt_cfb_shift(crypt_cfb_iv, buf, chunksize); + crypt_cfb_xor((unsigned char *) buf, temp, chunksize); + if (!decrypt) + crypt_cfb_shift(crypt_cfb_iv, buf, chunksize); + len -= chunksize; + buf += chunksize; + } +} + +SV* decrypt_password(SV* password) { + size_t len = sv_len(password); + char *tmp = (char*)malloc(len); + memcpy(tmp,SvPVbyte(password,len),len); + crypt_cfb_buf(PASSCRYPT_KEY, tmp, len, 1, 1 ); + return newSVpvn(tmp,len); +} diff --git a/lib/Config/ClawsMail/Server.pm b/lib/Config/ClawsMail/Server.pm new file mode 100644 index 0000000..e3eefab --- /dev/null +++ b/lib/Config/ClawsMail/Server.pm @@ -0,0 +1,29 @@ +package Config::ClawsMail::Server; +use Moo; +use Types::Standard qw(Str Enum); +use Config::ClawsMail::Password; +use namespace::clean; + +has [qw(host port)] => ( + is => 'ro', + required => 1, + isa => Str, +); + +has [qw(user_id password)] => ( + is => 'ro', + isa => Str, +); + +has ssl => ( + is => 'ro', + isa => Enum[qw(no ssl starttls)], + default => sub { 'no' }, +); + +sub cleartext_password { + my ($self) = @_; + return Config::ClawsMail::Password::cleartext_password($self->password); +} + +1; -- cgit v1.2.3