aboutsummaryrefslogtreecommitdiff
path: root/debian/patches/0006-file-crypt.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/0006-file-crypt.patch')
-rw-r--r--debian/patches/0006-file-crypt.patch239
1 files changed, 239 insertions, 0 deletions
diff --git a/debian/patches/0006-file-crypt.patch b/debian/patches/0006-file-crypt.patch
new file mode 100644
index 0000000..532b3ed
--- /dev/null
+++ b/debian/patches/0006-file-crypt.patch
@@ -0,0 +1,239 @@
+--- a/perl/lib/Wallet/Config.pm
++++ b/perl/lib/Wallet/Config.pm
+@@ -765,11 +765,42 @@ with this ACL type. This variable must
+
+ =cut
+
++our $LDAP_SECRET;
++
++=item LDAP_SECRET
++
++Specifies an LDAP URL that is used to retrieve the secret to use when
++encrypting and decrypting file objects. The url must not include the
++hostname. LDAP_HOST will be used as the hostname to bind to. The
++Kerberos ticket cache specified in LDAP_CACHE is used when connecting
++to the LDAP server. GSS-API authentication is always used; there is
++currently no support for any other type of bind. The ticket cache
++must be for a principal with access to retrieve the secret. This
++variable and LDAP_CACHE must be set to use file object encryption.
++
++=cut
++
++our $LDAP_SECRET_PREFIX;
++
++=item LDAP_SECRET_PREFIX
++
++Specifies the prefix to be used when generating storing an encrypted
++file object. The prefix is used to determine whether or not a file
++object has been stored encrypted. This allows the gradual transition
++from unencrypted file objects to encrypted file objects. When file
++object encryption is enable any "get" of an unencyrpted file object
++will result in the replacement of the unencrypted object with an
++encrypted object.
++
++=cut
++
+ our $LDAP_CACHE;
+
+ =back
+
+-Finally, depending on the structure of the LDAP directory being queried,
++=head2 LDAP Principal Mapping
++
++Depending on the structure of the LDAP directory being queried,
+ there may not be any attribute in the directory whose value exactly
+ matches the Kerberos principal. The attribute designated by
+ LDAP_FILTER_ATTR may instead hold a transformation of the principal name
+@@ -794,6 +825,27 @@ Note that this example only removes the
+ Any principal from some other realm will be left fully qualified, and then
+ presumably will not be found in the directory.
+
++=head2 File Object Encryption
++
++The default encryption method use is based on the twofish cypher. If
++another encryption method is desired then the perl function file_crypt
++should be defined. The function must accept three parameters: the
++action to preform, the encryption secret, and the string to encrypt or
++decrypt. For example:
++
++ sub file_crypt {
++ use Crypt::RC4;
++ my ($action, $secret, $string) = @_;
++
++ my $return_string;
++ if ($action eq 'encrypt') {
++ $return_string = RC4($secret, $string);
++ } elsif ($action eq 'decrypt') {
++ $return_string = RC4($secret, $string);
++ }
++ return $return_string;
++ }
++
+ =head1 NETDB ACL CONFIGURATION
+
+ These configuration variables are only needed if you intend to use the
+--- a/perl/lib/Wallet/Object/File.pm
++++ b/perl/lib/Wallet/Object/File.pm
+@@ -20,6 +20,7 @@ use warnings;
+ use Digest::MD5 qw(md5_hex);
+ use File::Copy qw(move);
+ use File::Slurp;
++use Wallet::ACL::LDAP::Attribute;
+ use Wallet::Config;
+ use Wallet::Object::Base;
+
+@@ -107,6 +108,114 @@ sub rename {
+ }
+
+ ##############################################################################
++# Encyption and decryption
++##############################################################################
++
++sub _get_crypt_key {
++ my ($self) = @_;
++
++ # ldap:///basedn?attr?scope?filter
++ my $url = $Wallet::Config::LDAP_SECRET;
++ $url =~ s{^ldap:///}{}xmsi;
++ if ($url eq $Wallet::Config::LDAP_SECRET) {
++ self->error("ERROR: Invalid LDAP URL $url");
++ exit 1;
++ }
++ my @parts = split /\?/, $url;
++ my $base = $parts[0];
++ my $attr = $parts[1];
++ my $scope = $parts[2];
++ my $filter = $parts[3];
++
++ # Search for the secret in the LDAP directory
++ my $ldap_obj = Wallet::ACL::LDAP::Attribute->new;
++ my $ldap = $ldap_obj->{ldap};
++ my $entry;
++ eval {
++ my @options = (base => $base,
++ filter => $filter,
++ scope => $scope,
++ attrs => [ $attr ]
++ );
++ my $search = $ldap->search (@options);
++ if ($search->count == 1) {
++ $entry = $search->pop_entry;
++ } elsif ($search->count > 1) {
++ die 'ERROR: ' . $search->count . " LDAP entries found for $filter";
++ } else {
++ die "ERROR: No entry found for $url";
++ }
++ };
++ if ($@ || !$entry) {
++ die "ERROR: LDAP search failed for $url";
++ }
++
++ my $return_val;
++ my $cnt = 0;
++ foreach my $return_attr ($entry->attributes) {
++ if (lc($return_attr) eq lc($attr)) {
++ $return_val = $entry->get_value($return_val);
++ $cnt++;
++ }
++ }
++ if (!$return_val) {
++ die "ERROR: LDAP search failed for $url";
++ }
++ if ($cnt !=1) {
++ die "ERROR: LDAP search return too many values ($url)";
++ }
++ return $return_val;
++}
++
++sub _file_crypt {
++ my ($self, $action, $string) = @_;
++
++ use Crypt::CBC;
++ use MIME::Base64;
++
++ my $return_string;
++ my $pre = $Wallet::Config::LDAP_SECRET_PREFIX;
++ my $key = $self->_get_crypt_key();
++
++ my $cipher = Crypt::CBC->new(
++ -key => $key,
++ -cipher => 'Twofish',
++ -padding => 'space',
++ -add_header => 1
++ );
++ if ($action eq 'encrypt') {
++ $return_string = $pre . encode_base64($cipher->encrypt($string));
++ } elsif ($action eq 'decrypt') {
++ if ($string =~ s/^$pre//xms) {
++ $return_string = $cipher->decrypt(decode_base64($string));
++ } else {
++ $return_string = $string;
++ }
++ } else {
++ my $msg = "ERROR: invalid action ($action)\n ";
++ $msg .= "INFO: action must be 'encrypt' or 'decrypt'\n";
++ $self->error($msg);
++ return;
++ }
++ return $return_string;
++}
++
++sub _file_decrypt {
++ my ($self, $data, $user, $host, $time) = @_;
++ my $undata = $self->_file_crypt('decrypt', $data);
++ if ($undata eq $data) {
++ $self->store($data, $user, $host, $time) = @_;
++ }
++ return $undata;
++}
++
++sub _file_encrypt {
++ my ($self, $data) = @_;
++ my $endata = $self->_file_crypt('encrypt', $data);
++ return $endata;
++}
++
++##############################################################################
+ # Core methods
+ ##############################################################################
+
+@@ -143,6 +253,9 @@ sub get {
+ $self->error ("cannot get $id: $!");
+ return;
+ }
++ if ($Wallet::LDAP::SECRET) {
++ $data = self->_file_decrypt($user, $host, $time, $data);
++ }
+ $self->log_action ('get', $user, $host, $time);
+ return $data;
+ }
+@@ -158,10 +271,17 @@ sub checksum {
+ }
+ my $path = $self->file_path;
+ my $this_checksum;
++ my $this_data;
++ my $this_endata = read_file($path);
++ if ($Wallet::Config::LDAP_SECRET) {
++ $this_data = $self->_file_decrypt($this_endata, $user, $host, $time)
++ } else {
++ $this_data = $this_endata;
++ }
+ if (defined (&Wallet::Config::file_checksum)) {
+- $this_checksum = Wallet::Config::file_checksum($path);
++ $this_checksum = Wallet::Config::file_checksum($this_data);
+ } else {
+- $this_checksum = md5_hex(read_file($path));
++ $this_checksum = md5_hex($this_data);
+ }
+ $self->log_action ('checksum', $user, $host, $time);
+ return $this_checksum;
+@@ -189,6 +309,9 @@ sub store {
+ $self->error ("cannot store $id: $!");
+ return;
+ }
++ if ($Wallet::Config::LDAP_SECRET) {
++ $data = $self->_file_encrypt($data);
++ }
+ unless (print FILE ($data) and close FILE) {
+ $self->error ("cannot store $id: $!");
+ close FILE;