Subject: | Two Phase Encryption does not work! |
I noticed this bug when running benchmarks to determine the speed
difference between using/not using encryption on RPC::PlServer.
Summary:
------------------------------------------------
When RPC::PlServer->{'client'} is changed, RPC::PlServer::Comm->
{'cipher'} is not.
When RPC::PlClient->{'client'} is changed, RPC::PlClient::Comm->
{'cipher'} is not.
Hence Second Phase Encryption does NOT work at all.
Full Description:
------------------------------------------------
RPC::PlServer::Comm is created from RPC::PlServer when the server is
first setup, hence the value for RPC::PlServer::Comm->{'cipher'} and
RPC::PlServer->{'cipher'} are the same.
In RPC::PlServer::Accept $self->{'cipher'} is changed to match the
user/client's cipher. However RPC::PlServer::Comm->{'cipher'} is NOT
changed.
Similarly, when RPC::PlClient->{'cipher'} is changed (as per the
examples in t/crypt.t and DBI::Proxy) RPC::PlClient::Comm->{'cipher'}
is not changed either.
Neither Comm->{'cipher'} is modified at a later time, hence both Comm
objects still use first phase encryption, even though it appears that
it has been changed. i.e. Second phase encryption does not work AT ALL.
Solutions:
My current solution is as follows:
------------------------------------------------
1. In RPC::PlClient add the method Cipher, which simply sets both
$self->{'cipher'} and $self->{'comm'}->{'cipher'} (attached). This
provides better encapsulation and prevents the user from having to
know to set both ciphers when changing encryption.
2. In the implementation of the server (i.e. MyServer) override the
Accept function to set the value of $self->{'comm'}->{'cipher'} to
$self->{'cipher'} after the user authentication has been done (see
attached example).
A better (but requires more low level changes) method:
------------------------------------------------
1. Still implement a Cipher method (as encapsulation is good) but only
have it set $self->{'cipher'}.
2. Change $self->{'comm'}->{'cipher'} from an object reference, to a
reference to a object reference.
e.g. In RPC::PlServer::Comm::new you have:
if (my $cipher = $attr->{'cipher'}){
$self->{'cipher'} = $cipher;
}
Changing to:
$self->{'cipher'} = \$attr->{'cipher'}
And then use:
${$self->{'cipher'}}->method (as the accessor)
would make sure any changes to RPC::PlClient->{'cipher'} are
automatically known by RPC::PlClient->{'comm'}->{'cipher'} as they
share the same variable.
Finally:
------------------------------------------------
It would be ideal if after login it were possible to disable
authentication for a client (to increase speed).
e.g. All clients log in using the cipher specified in MyServer->new
(First Phase).
When a user from another server logs in their cipher is set to their
own (Second Phase). However, when 127.0.0.1 logs in, it is preferable
that encryption is disabled (as this increases speed dramtically).
I have implemented a workaround by setting the client 127.0.0.1's
cipher to -1 (cipher must be a true value to be passed through
Accept). At the end of Accept, the -1 is caught and then changed to
undef (see example in Accept override (attached)).
It would be great if this could be added to RPC::PlServer::Accept to
allow a client to disable encryption for their session.
e.g. In MyServer:
$clients = [
{
mask => '^127\.0\.0\.1$',
users => ['localhost'],
accept => 1,
cipher => -1
},
]
At end of RPC::PlServer::Accept:
$self->{'cipher'} = undef if ($self->{'cipher'} eq -1);
1;
Subject: | rpc-plclient-cipher.txt |
sub Cipher {
my $self = shift;
if (@_){
$self->{'cipher'} = $_[0];
$self->{'comm'}->{'cipher'} = $_[0] if ($self->{'comm'});
}
$self->{'cipher'};
}
Subject: | rpc-plserver-Accept-override.txt |
sub Accept {
my ($self) = @_;
return 0 if (!$self->SUPER::Accept);
# Disable Cipher
$self->{'cipher'} = undef if ($self->{'cipher'} eq -1);
# Move cipher into comm
if ($self->{'cipher'} ne $self->{'comm'}->{'cipher'}){
$self->{'comm'}->{'cipher'} = $self->{'cipher'};
}
1;
}