From 3066a0e577e7cf502cb0491b94cfd80601b69feb Mon Sep 17 00:00:00 2001 From: Mirko Tietgen Date: Sun, 21 Oct 2012 21:26:44 +0200 Subject: [PATCH] Bug 8897 [ENH] Optional GnuPG encryption of outgoing emails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enhancement allows GnuPG encryption of emails sent by Koha. Initial patch with some basic functionality. TODO: key management, attachments … --- C4/GnuPG.pm | 72 ++++++++++++++++++++ C4/Letters.pm | 7 ++ C4/Message.pm | 5 ++ installer/data/mysql/sysprefs.sql | 2 + installer/data/mysql/updatedatabase.pl | 8 ++ .../prog/en/modules/admin/preferences/admin.pref | 8 ++ 6 files changed, 102 insertions(+), 0 deletions(-) create mode 100644 C4/GnuPG.pm diff --git a/C4/GnuPG.pm b/C4/GnuPG.pm new file mode 100644 index 0000000..9d08d51 --- /dev/null +++ b/C4/GnuPG.pm @@ -0,0 +1,72 @@ +package C4::GnuPG; + +# Copyright 2012 Mirko Tietgen +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use strict; +use warnings; +use C4::Context; +use Crypt::GPG; + +=head1 C4::GnuPG + +C4::GnuPG + +=head1 Description + +Provides methods to interact with GnuPG via Crypt::GPG for the purpose of encrypting emails to patrons + +=cut + +my $gpg = new Crypt::GPG; +$gpg->gpgbin(C4::Context->preference('GnuPGPPath')); +$gpg->secretkey(C4::Context->preference('KohaAdminEmailAddress')); +$gpg->passphrase(C4::Context->preference('GnuPGPassphrase')); + +=head2 encrypt + +Take email content and patron's email address, send back encrypted content. Call like + +$content = C4::GnuPG->encrypt($content, $patronemail); + +=cut + +sub encrypt { + my ($self, $content, $patronemail) = @_; + $content = $gpg->encrypt($content, $patronemail); + return $content; +} + +=head2 does_exist + +Check if there is a GnuPG key for the patron's email address. Call like + +if ( C4::GnuPG->does_exist($useremail) = 1 ) { + # … encrypt … +} + +=cut + +sub does_exist { + my ($self, $patronemail) = @_; + if ( $gpg->keydb($patronemail) ) { + return 1; + } + else { + return 0; + } +} diff --git a/C4/Letters.pm b/C4/Letters.pm index f646241..4333bad 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -33,6 +33,7 @@ use Date::Calc qw( Add_Delta_Days ); use Encode; use Unicode::Normalize; use Carp; +use C4::GnuPG; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); @@ -782,6 +783,12 @@ sub EnqueueLetter { ); } + # gnupg encrypt content if encryption enabled and key for patron present + my $useremail = $params->{'to_address'}; + if ( (C4::Context->preference("GnuPGPassphrase")) && (C4::Context->preference("GnuPGPassphrase") ne '') && (C4::GnuPG->does_exist($params->{'to_address'}) == 1) ) { + $params->{'letter'}->{'content'} = C4::GnuPG->encrypt($params->{'letter'}->{'content'}, $params->{'to_address'}); + } + my $dbh = C4::Context->dbh(); my $statement = << 'ENDSQL'; INSERT INTO message_queue diff --git a/C4/Message.pm b/C4/Message.pm index a63b3ca..5b3caff 100644 --- a/C4/Message.pm +++ b/C4/Message.pm @@ -25,6 +25,7 @@ use C4::Context; use C4::Letters; use YAML::Syck; use Carp; +use C4::GnuPG; =head1 NAME @@ -322,6 +323,10 @@ sub append { push @{$metadata->{body}}, $item; $self->metadata($metadata); my $new_content = $self->render_metadata($format); + # gnupg encrypt content if encryption enabled and key for patron present + if ( (C4::Context->preference("GnuPGPassphrase")) && (C4::Context->preference("GnuPGPassphrase") ne '') && (C4::GnuPG->does_exist($self->{'to_address'}) == 1) ) { + $new_content = C4::GnuPG->encrypt($new_content, $self->{'to_address'}) + } return $self->content($new_content); } diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 0cc5a54..838d3e6 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -388,3 +388,5 @@ INSERT INTO systempreferences (variable, value, options, explanation, type) VALU INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HoldsToPullStartDate','2','Set the default start date for the Holds to pull list to this many days ago',NULL,'Integer'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('alphabet','A B C D E F G H I J K L M N O P Q R S T U V W X Y Z','Alphabet than can be expanded into browse links, e.g. on Home > Patrons',NULL,'free'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('RefundLostItemFeeOnReturn', '1', 'If enabled, the lost item fee charged to a borrower will be refunded when the lost item is returned.', NULL, 'YesNo'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('GnuPGPath','/usr/bin/gpg','Path to GnuPG','','free'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('GnuPGPassphrase','','Passphrase for GnuPG','','free'); diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 676bb3e..0552653 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -6134,6 +6134,14 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { SetVersion ($DBversion); } +$DBversion = 'XXX'; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('GnuPGPath','/usr/bin/gpg','Path to GnuPG','','free');"); + $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('GnuPGPassphrase','','Passphrase for GnuPG','','free');"); + print "Upgrade to $DBversion done (Add GnuPGPath and GnuPGPassphrase sysprefs)\n"; + SetVersion ($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref index 4e907e1..cf42fdf 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref @@ -40,6 +40,14 @@ Administration: yes: Allow no: "Don't allow" - staff and patrons to create and view saved lists of books. + - + - GnuPG passphrase used to encrypt outgoing emails from KohaAdminEmailAddress. Leave blank to disable encryption. You must have GnuPG running and a keypair setup for KohaAdminEmailAddress to use this. + - pref: GnuPGPassphrase + class: password + - + - Path to GnuPG + - pref: GnuPGPath + - class: textarea Login options: - - pref: insecure -- 1.7.2.5