qpsmtpd-gpg/src/encrypt_gpg

118 lines
2.8 KiB
Plaintext
Raw Normal View History

=head1 NAME
encrypt_gpg - encrypt incoming emails whith the recipients PGP public key
=head1 DESCRIPTION
Plugin checks, if there is a trusted public key for each of the recipients
of the incoming email, in the GnuPG public key ring of the user running qpsmtpd.
If such a key exists the email is encrypted with these keys.
=head1 PER USER CONFIG
The file encrypt_gpg_user is a lookup up table for eMails in the form:
email encryption_type
possible values for encryption_type are none and pgpmime. The standard is
pgpmime. With none the encryption can be deactivated completely.
=cut
use Qpsmtpd::DSN;
use Mail::GnuPG;
use GnuPG::Interface;
use MIME::Parser;
#init
sub init {
my ( $self, $qp, @args ) = @_;
# get us the user config file
my @encrypted_user_config = $self->qp->config("encrypt_gpg_user");
my %user_hash;
for my $e (@encrypted_user_config) {
my ( $email, $encryption_type ) = split /\s+/, $e, 2;
$user_hash{$email}=$encryption_type;
}
$self->{_gpg_user}=\%user_hash;
}
# search for the users public key
# the key id can be given in a file or is search for on a keyserver
# and create a Mail::GnuPG object
sub hook_rcpt {
my ( $self, $transaction, $recipient, %param ) = @_;
my $rcpt = $recipient;
$rcpt =~ s/<//;
$rcpt =~ s/>//;
#get us the user hash
my %user_hash = %{$self->{_gpg_user}};
if (defined($user_hash{$rcpt}) && $user_hash{$rcpt} eq "none" ) {
$self->log( LOGINFO, "GPG: encryption deactivated for email " .$rcpt );
$self->{_gpg_on}=0;
return OK;
}
$self->{_gpg_on}=1;
my $gpg = new Mail::GnuPG( keydir => '/var/spool/qpsmtpd/.gnupg/', always_trust => 1 );
if ( !$gpg->has_public_key($rcpt) ) {
$self->log( LOGINFO, "GPG: no key for -" . $rcpt . "- found !" );
$self->{_gpg_on}=0;
return OK;
}
# save gnupg object for rest of the session
$self->{_gpg} = $gpg;
$self->{_gpg_recipient} = $rcpt;
return (OK);
}
#check if mail is already encrypted, otherwise encrypt it
sub hook_data_post {
my ( $self, $transaction ) = @_;
# if gpg is deactivated, skip this hook
if ($self->{_gpg_on}==0) {
return OK;
}
#parse queued message
my $parser = new MIME::Parser();
$parser->decode_bodies(1);
$parser->output_to_core(1);
my $mime = $parser->parse_open( $transaction->body_filename() );
#check if email is already encrypted
if ( $self->{_gpg}->is_encrypted($mime) ) {
$self->log( LOGINFO, "GPG: email already PGP encrypted" );
return OK;
}
#encrypt message
my $code;
$code = $self->{_gpg}->mime_encrypt( $mime, $self->{_gpg_recipient} );
if ( $code != 0 ) {
$self->log( LOGERROR, "GPG: " . $self->{_gpg}->{last_message}->[0] );
return OK;
}
# rewrite the queued message
open my $queued_mail, ">" . $transaction->body_filename();
print $queued_mail $mime->stringify;
close $queued_mail;
return OK;
}