From 65634d7014b978b9fd0fc1b5e53cb8c3ce4ac758 Mon Sep 17 00:00:00 2001 From: Rene Krenn Date: Tue, 7 Jul 2020 12:40:25 +0200 Subject: [PATCH] TT#84329 encrypt/decrypt password, weppassword, pin Change-Id: I74ae79b798955e6e20c32a644c739d81786f90c0 --- lib/NGCP/Panel/Role/API/Subscribers.pm | 13 +++- lib/NGCP/Panel/Role/API/VoicemailSettings.pm | 22 +++++++ lib/NGCP/Panel/Utils/Encryption.pm | 64 ++++++++++++++++++++ lib/NGCP/Panel/Utils/Subscriber.pm | 12 ++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 lib/NGCP/Panel/Utils/Encryption.pm diff --git a/lib/NGCP/Panel/Role/API/Subscribers.pm b/lib/NGCP/Panel/Role/API/Subscribers.pm index 801a2914f3..c65c4724f2 100644 --- a/lib/NGCP/Panel/Role/API/Subscribers.pm +++ b/lib/NGCP/Panel/Role/API/Subscribers.pm @@ -18,6 +18,7 @@ use NGCP::Panel::Utils::Subscriber; use NGCP::Panel::Utils::Events; use NGCP::Panel::Utils::DateTime; use NGCP::Panel::Utils::Contract qw(); +use NGCP::Panel::Utils::Encryption qw(); sub resource_name{ return 'subscribers'; @@ -151,7 +152,17 @@ sub resource_from_item { }else{ $resource{lock} = undef; } - unless ($c->user->show_passwords) { + if ($c->user->show_passwords) { + foreach my $k(qw/password webpassword/) { + eval { + $resource{$k} = NGCP::Panel::Utils::Encryption::encrypt_rsa($c,$resource{$k}); + }; + if ($@) { + $c->log->error("Failed to encrypt $k '$resource{$k}': " . $@); + delete $resource{$k}; + } + } + } else { foreach my $k(qw/password webpassword/) { delete $resource{$k}; } diff --git a/lib/NGCP/Panel/Role/API/VoicemailSettings.pm b/lib/NGCP/Panel/Role/API/VoicemailSettings.pm index f10230878a..9f93e51984 100644 --- a/lib/NGCP/Panel/Role/API/VoicemailSettings.pm +++ b/lib/NGCP/Panel/Role/API/VoicemailSettings.pm @@ -10,6 +10,7 @@ use boolean qw(true); use Data::HAL qw(); use Data::HAL::Link qw(); use HTTP::Status qw(:constants); +use NGCP::Panel::Utils::Encryption qw(); sub _item_rs { my ($self, $c) = @_; @@ -84,6 +85,16 @@ sub resource_from_item { $resource->{delete} = delete $resource->{delete} eq 'yes' ? 1 : 0; $resource->{attach} = delete $resource->{attach} eq 'yes' ? 1 : 0; $resource->{sms_number} = delete $resource->{pager}; + + foreach my $k(qw/pin/) { + eval { + $resource->{$k} = NGCP::Panel::Utils::Encryption::encrypt_rsa($c,$resource->{$k}); + }; + if ($@) { + $c->log->error("Failed to encrypt $k '$resource->{$k}': " . $@); + delete $resource->{$k}; + } + } return $resource; } @@ -101,6 +112,17 @@ sub item_by_id { sub update_item { my ($self, $c, $item, $old_resource, $resource, $form) = @_; + foreach my $k (qw/pin/) { + eval { + $resource->{$k} = NGCP::Panel::Utils::Encryption::decrypt_rsa($c,$resource->{$k}); + }; + if ($@) { + $c->log->error("Failed to encrypt $k '$resource->{$k}': " . $@); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Failed to encrypt $k."); + return; + } + } + $form //= $self->get_form($c); return unless $self->validate_form( c => $c, diff --git a/lib/NGCP/Panel/Utils/Encryption.pm b/lib/NGCP/Panel/Utils/Encryption.pm new file mode 100644 index 0000000000..84c2787c04 --- /dev/null +++ b/lib/NGCP/Panel/Utils/Encryption.pm @@ -0,0 +1,64 @@ +package NGCP::Panel::Utils::Encryption; +use Sipwise::Base; + +use Crypt::OpenSSL::RSA; +use MIME::Base64; + +my $rsa_public_key_file = '/etc/ngcp-panel/rsa_public_key.pem'; +my $rsa_private_key_file = '/etc/ngcp-panel/rsa_private_key.pem'; + +my $rsa_encrytper; +my $rsa_decrytper; + +sub _check_encrypted { + + my $c = shift; + my $encrypted = $c->req->param('encrypted'); + if (length($encrypted) + and ('rsa' eq lc($encrypted) + or '1' eq $encrypted + or 'true' eq lc($encrypted))) { + return 1; + } + return 0; + +} + +sub encrypt_rsa { + + my ($c,$plaintext) = @_; + return unless defined $plaintext; + if (_check_encrypted($c)) { + unless ($rsa_encrytper) { + $rsa_encrytper = Crypt::PK::RSA->new(); + $rsa_encrytper->import_key($rsa_public_key_file); + die('public key file contains a private key') if $rsa_encrytper->is_private(); + } + my $ciphertext = $rsa_encrytper->encrypt($plaintext); + $ciphertext = encode_base64($ciphertext, ''); + return $ciphertext; + } + return $plaintext; + +} + +sub decrypt_rsa { + + my ($c,$ciphertext) = @_; + return unless defined $ciphertext; + if (_check_encrypted($c)) { + unless ($rsa_decrytper) { + $rsa_decrytper = Crypt::PK::RSA->new(); + $rsa_decrytper->import_key($rsa_private_key_file); + die('private key file contains a public key') unless $rsa_decrytper->is_private(); + } + $ciphertext = decode_base64($ciphertext); + my $plaintext = $rsa_decrytper->decrypt($ciphertext); + #$c->log->debug("decrypted: $plaintext"); + return $plaintext; + } + return $ciphertext; + +} + +1; diff --git a/lib/NGCP/Panel/Utils/Subscriber.pm b/lib/NGCP/Panel/Utils/Subscriber.pm index c1bcd5287a..c5b1474fc4 100644 --- a/lib/NGCP/Panel/Utils/Subscriber.pm +++ b/lib/NGCP/Panel/Utils/Subscriber.pm @@ -24,6 +24,7 @@ use HTTP::Status qw(:constants); use IPC::System::Simple qw/capturex/; use File::Slurp qw/read_file/; use Redis; +use NGCP::Panel::Utils::Encryption qw(); my %LOCK = ( 0, 'none', @@ -319,6 +320,17 @@ sub prepare_resource { } } } + + foreach my $k(qw/password webpassword/) { + eval { + $resource->{$k} = NGCP::Panel::Utils::Encryption::decrypt_rsa($c,$resource->{$k}); + }; + if ($@) { + $c->log->error("Failed to decrypt $k '$resource->{$k}': " . $@); + &{$err_code}(HTTP_UNPROCESSABLE_ENTITY, "Failed to decrypt $k."); + return; + } + } return unless &$validate_code($resource); #my ($form) = $self->get_form($c);