Commit 6d0d3010 authored by sikeda's avatar sikeda
Browse files

[dev] Refactoring: Now S/MIME signing and encryption will be done by bulk.pl.

- $message->{shelved}{smime_sign} & $message->{shelved}{smime_encrypt} attributes are set to indicate signing/encryption are required.
- Messages are checked if encryption is possible on all recipients before they are stored into bulk spool.
- As a side effect, messages sent by robots will be signed if keys are available.

Known issue: This feature won't be applied to the messages stored into bulk spool before upgrading.


git-svn-id: https://subversion.renater.fr/sympa/branches/sympa-6.2-branch@11296 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent f1418f42
......@@ -2458,8 +2458,6 @@ sub send_file {
my ($self, $tpl, $who, $robot, $context) = @_;
Log::do_log('debug2', '(%s, %s, %s)', $tpl, $who, $robot);
my $sign_mode;
my $data = tools::dup_var($context);
## Any recipients
......@@ -2571,26 +2569,21 @@ sub send_file {
$data->{'list'}{'owner'} = $self->get_owners();
$data->{'list'}{'dir'} = $self->{'dir'};
## Sign mode
if ( $Conf::Conf{'openssl'}
&& (-r $self->{'dir'} . '/cert.pem')
&& (-r $self->{'dir'} . '/private_key')) {
$sign_mode = 'smime';
}
# Sign mode
my $smime_sign = tools::smime_find_keys($self, 'sign');
# if the list have it's private_key and cert sign the message
# . used only for the welcome message, could be usefull in other case?
# . used only for the welcome message, could be useful in other case?
# . a list should have several certificates and use if possible a
# certificate
# issued by the same CA as the recipient CA if it exists
if ($sign_mode and $sign_mode eq 'smime') {
# certificate issued by the same CA as the recipient CA if it exists
if ($smime_sign) {
$data->{'fromlist'} = $self->get_list_address();
$data->{'replyto'} = $self->get_list_address('owner');
} else {
$data->{'fromlist'} = $self->get_list_address('owner');
}
$data->{'from'} = $data->{'fromlist'} unless ($data->{'from'});
$data->{'from'} ||= $data->{'fromlist'};
$data->{'return_path'} ||= $self->get_list_address('return_path');
$data->{'boundary'} = '----------=_' . tools::get_message_id($robot)
......@@ -2599,6 +2592,10 @@ sub send_file {
my $message =
Sympa::Message->new_from_template($self, $filename, $who, $data);
# Shelve S/MIME signing.
$message->{shelved}{smime_sign} = 1
if $smime_sign;
# Shelve DKIM signing.
$message->{shelved}{dkim_sign} = 1
if Conf::get_robot_conf($self->{'domain'}, 'dkim_feature') eq 'on'
and
......@@ -2612,9 +2609,8 @@ sub send_file {
$message
and defined Sympa::Mail::sending(
$message, $who, $data->{'return_path'},
'priority' => Conf::get_robot_conf($robot, 'sympa_priority'),
'sign_mode' => $sign_mode,
'use_bulk' => $use_bulk,
'priority' => Conf::get_robot_conf($robot, 'sympa_priority'),
'use_bulk' => $use_bulk,
)
) {
Log::do_log('err', 'Could not send template %s to %s',
......
......@@ -205,25 +205,54 @@ sub mail_message {
push @sendtobypacket, \@tab;
}
# Shelve personalization.
$message->{shelved}{merge} = 1
if tools::smart_eq($list->{'admin'}{'merge_feature'}, 'on');
# Since message for each recipient should be encrypted by bulk mailer,
# check if encryption will be successful.
if ($message->{'smime_crypted'}) {
foreach my $bulk_of_rcpt (@sendtobypacket) {
foreach my $email (@{$bulk_of_rcpt}) {
if ($email !~ /@/) {
Log::do_log('err',
'incorrect call for encrypt with incorrect number of recipient'
);
return undef;
}
my $new_message = $message->dup;
unless ($new_message->smime_encrypt($email)) {
Log::do_log(
'err',
'Unable to encrypt message to list %s for recipient %s',
$list,
$email
);
return undef;
}
}
}
$message->{shelved}{smime_encrypt} = 1;
}
# if not specified, delivery time is right now (used for sympa messages
# etc.)
my $delivery_date =
$list->get_next_delivery_date
|| $message->{'date'}
|| time;
return $numsmtp
if (
sendto(
'message' => $message,
'from' => $from,
'rcpt' => \@sendtobypacket,
'listname' => $list->{'name'},
'priority' => $list->{'admin'}{'priority'},
'delivery_date' =>
($list->get_next_delivery_date || $message->{'date'} || time),
'robot' => $robot,
'encrypt' => $message->{'smime_crypted'},
'use_bulk' => 1,
'tag_as_last' => $tag_as_last
)
if sending(
$message, \@sendtobypacket, $from,
'priority' => $list->{'admin'}{'priority'},
'delivery_date' => $delivery_date,
'use_bulk' => 1,
'tag_as_last' => $tag_as_last
);
return undef;
}
......@@ -298,110 +327,8 @@ sub reaper {
return $i;
}
### PRIVATE FUNCTIONS ###
####################################################
# sendto
####################################################
# send messages, S/MIME encryption if needed,
# grouped sending (or not if encryption)
#
# IN: $msg_header (+): message header : MIME::Head object
# $msg_body (+): message body
# $from (+): message from
# $rcpt(+) : ref(SCALAR) | ref(ARRAY) - message recepients
# $listname : use only to format return_path if VERP on
# $robot(+) : robot
# $encrypt : 'smime_crypted' | undef
# $use_bulk : if defined, send message using bulk
#
# OUT : 1 - call to sending
#
####################################################
sub sendto {
my %params = @_;
my $message = $params{'message'};
my $from = $params{'from'};
my $rcpt = $params{'rcpt'};
my $listname = $params{'listname'};
my $robot = $params{'robot'};
my $priority = $params{'priority'};
my $encrypt = $params{'encrypt'};
my $use_bulk = $params{'use_bulk'};
my $tag_as_last = $params{'tag_as_last'};
Log::do_log(
'debug',
'(%s, from=%s, listname=%s, encrypt=%s, priority=%s, last=%s, use_bulk=%s',
$message,
$from,
$listname,
$encrypt,
$priority,
$tag_as_last,
$use_bulk
);
my $delivery_date = $params{'delivery_date'};
# if not specified, delivery tile is right now (used for sympa messages
# etc)
$delivery_date = time()
unless $delivery_date;
my $msg;
if ($encrypt and $encrypt eq 'smime_crypted') {
# Encrypt message for each recipient and send the message.
# This MUST be moved to the bulk mailer. This way, personalize
# (merge) will be applied after the S/MIME encryption is applied!
# This is a bug!
foreach my $bulk_of_rcpt (@{$rcpt}) {
foreach my $email (@{$bulk_of_rcpt}) {
if ($email !~ /@/) {
Log::do_log('err',
'incorrect call for encrypt with incorrect number of recipient'
);
return undef;
}
my $new_message = $message->dup;
unless ($new_message->smime_encrypt($email)) {
Log::do_log(
'err',
'Unable to encrypt message to list %s for recipient %s',
$listname,
$email
);
return undef;
}
unless (
sending(
$new_message, $email, $from,
'priority' => $priority,
'delivery_date' => $delivery_date,
'use_bulk' => $use_bulk,
'tag_as_last' => $tag_as_last
)
) {
Log::do_log('err', 'Failed to send encrypted message');
return undef;
}
$tag_as_last = 0;
}
}
} else {
my $result = sending(
$message, $rcpt, $from,
'priority' => $priority,
'delivery_date' => $delivery_date,
'use_bulk' => $use_bulk,
'tag_as_last' => $tag_as_last
);
return $result;
}
return 1;
}
#DEPRECATED. Use mail_message().
#sub sendto;
####################################################
# sending
......@@ -415,7 +342,6 @@ sub sendto {
# -$rcpt: SCALAR | ref(ARRAY) - recipients for SMTP "RCPT To:" field.
# -$from: for SMTP, "MAIL From:" field; for spool sending, "X-Sympa-From"
# field
# -sign_mode => mode: 'smime' for signing
# -use_bulk => boolean
#
# OUT : 1 - call to smtpto (sendmail) | 0 - push in spool
......@@ -439,8 +365,6 @@ sub sending {
$robot_id = '*';
}
my $sign_mode = $params{'sign_mode'};
my $sympa_email = $params{'sympa_email'};
my $priority_message = $params{'priority'};
my $priority_packet =
Conf::get_robot_conf($robot_id, 'sympa_packet_priority');
......@@ -451,14 +375,6 @@ sub sending {
my $sympa_file;
my $fh;
if ($sign_mode and $sign_mode eq 'smime') {
unless ($message->smime_sign) {
Log::do_log('notice', 'Unable to sign message from %s',
$listname);
return undef;
}
}
if ($use_bulk) {
# in that case use bulk tables to prepare message distribution
my $bulk_code = Sympa::Bulk::store(
......@@ -485,7 +401,7 @@ sub sending {
# it to standard spool
Log::do_log('debug', "NOT USING BULK");
$sympa_email = Conf::get_robot_conf($robot_id, 'sympa');
my $sympa_email = Conf::get_robot_conf($robot_id, 'sympa');
$sympa_file =
"$send_spool/T.$sympa_email." . time . '.' . int(rand(10000));
unless (open TMP, ">$sympa_file") {
......@@ -550,21 +466,17 @@ sub sending {
#
##############################################################################
sub smtpto {
my ($from, $rcpt, $robot, $msgkey, $sign_mode) = @_;
Log::do_log('debug2',
'(from: %s, rcpt:%s, robot:%s, msgkey:%s, sign_mode: %s)',
$from, $rcpt, $robot, $msgkey, $sign_mode);
Log::do_log('debug2', '(%s, %s, %s, %s)', @_);
my ($from, $rcpt, $robot, $msgkey) = @_;
unless ($from) {
Log::do_log('err', 'Missing Return-Path');
}
if (ref($rcpt) eq 'SCALAR') {
Log::do_log('debug2', '(%s, %s, %s)', $from, $$rcpt, $sign_mode);
Log::do_log('debug2', '(%s, %s)', $from, $$rcpt);
} elsif (ref($rcpt) eq 'ARRAY') {
Log::do_log('debug2', '(%s, %s, %s)', $from, join(',', @{$rcpt}),
$sign_mode);
Log::do_log('debug2', '(%s, %s)', $from, join(',', @{$rcpt}));
}
my ($pid, $str);
......
......@@ -129,6 +129,10 @@ sub send_global_file {
}
$data->{'sender'} = $who;
# Sign mode
my $smime_sign = tools::smime_find_keys($robot, 'sign');
$data->{'conf'}{'version'} = $main::Version;
$data->{'from'} = "$data->{'conf'}{'email'}\@$data->{'conf'}{'host'}"
unless ($data->{'from'});
......@@ -144,6 +148,10 @@ sub send_global_file {
Sympa::Message->new_from_template($robot, $filename, $who, $data);
return $message->as_string if $options->{'parse_and_return'};
# Shelve S/MIME signing.
$message->{shelved}{smime_sign} = 1
if $smime_sign;
# Shelve DKIM signing.
$message->{shelved}{dkim_sign} = 1
if Conf::get_robot_conf($robot, 'dkim_feature') eq 'on'
and Conf::get_robot_conf($robot, 'dkim_add_signature_to') =~
......@@ -155,11 +163,9 @@ sub send_global_file {
unless (
$message
and defined Sympa::Mail::sending(
$message, $who,
$data->{'return_path'},
$message, $who, $data->{'return_path'},
'priority' => Conf::get_robot_conf($robot, 'sympa_priority'),
'sign_mode' => $data->{'sign_mode'}, #FIXME: may not be set.
'use_bulk' => $use_bulk,
'use_bulk' => $use_bulk,
)
) {
Log::do_log('err', 'Could not send template %s to %s',
......
......@@ -416,6 +416,7 @@ while (!$end) {
}
if ( $message->{shelved}{merge}
or $message->{shelved}{smime_encrypt}
or $message->{shelved}{tracking}) {
# message needs personalization
my $key;
......@@ -461,6 +462,27 @@ while (!$end) {
delete $new_message->{shelved}{merge};
}
if ($new_message->{shelved}{smime_sign}) {
$new_message->smime_sign;
delete $new_message->{shelved}{smime_sign};
}
if ($new_message->{shelved}{smime_encrypt}) {
unless ($new_message->smime_encrypt($rcpt)) {
#FIXME: Mark packet as "bad".
Log::do_log(
'err',
'Unable to encrypt message %s from %s for recipient %s',
$new_message,
$list,
$rcpt
);
last; # foreach $rcpt
}
delete $new_message->{shelved}{smime_encrypt};
}
if (Conf::get_robot_conf($robot, 'dkim_feature') eq 'on') {
$new_message->remove_invalid_dkim_signature;
}
......@@ -487,9 +509,14 @@ while (!$end) {
close SMTP;
}
} else {
# message doesn't need personalization, so can be sent by packet.
my $new_message = $message->dup;
# message doesn't need personalization, so can be sent by packet.
if ($new_message->{shelved}{smime_sign}) {
$new_message->smime_sign;
delete $new_message->{shelved}{smime_sign};
}
if (Conf::get_robot_conf($robot, 'dkim_feature') eq 'on') {
$new_message->remove_invalid_dkim_signature;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment