TT#12601 API must implement bcrypt auth/migration

Not only the web login must support bcrypt auth, but also the API
access.

Change-Id: Iee7c5b7a073000e797725919a5752f9eaf77c958
changes/78/12078/2
Andreas Granig 8 years ago
parent 7a5c1eb12a
commit 5918c162e1

@ -7,7 +7,6 @@ use parent 'Catalyst::Controller';
use NGCP::Panel::Form::Login;
use NGCP::Panel::Utils::Admin;
use Crypt::Eksblowfish::Bcrypt qw/bcrypt_hash en_base64 de_base64/;
sub index :Path Form {
my ( $self, $c, $realm ) = @_;
@ -30,64 +29,7 @@ sub index :Path Form {
$c->log->debug("*** Login::index user=$user, pass=****, realm=$realm");
my $res;
if($realm eq 'admin') {
my $dbadmin = $c->model('DB')->resultset('admins')->find({
login => $user,
is_active => 1,
});
if(defined $dbadmin && defined $dbadmin->saltedpass) {
$c->log->debug("login via bcrypt");
my ($db_b64salt, $db_b64hash) = split /\$/, $dbadmin->saltedpass;
my $salt = de_base64($db_b64salt);
my $usr_b64hash = en_base64(bcrypt_hash({
key_nul => 1,
cost => NGCP::Panel::Utils::Admin::get_bcrypt_cost(),
salt => $salt,
}, $pass));
# fetch again to load user into session etc (otherwise we could
# simply compare the two hashes here :(
$res = $c->authenticate(
{
login => $user,
saltedpass => $db_b64salt . '$' . $usr_b64hash,
'dbix_class' => {
searchargs => [{
-and => [
login => $user,
is_active => 1,
],
}],
}
}, 'admin_bcrypt'
);
} elsif(defined $dbadmin) { # we already know if the username is wrong, no need to check again
# check md5 and migrate over to bcrypt on success
$c->log->debug("login via md5");
$res = $c->authenticate(
{
login => $user,
md5pass => $pass,
'dbix_class' => {
searchargs => [{
-and => [
login => $user,
is_active => 1,
],
}],
}
}, 'admin');
if($res) {
# login ok, time to move user to bcrypt hashing
$c->log->debug("migrating to bcrypt");
my $saltedpass = NGCP::Panel::Utils::Admin::generate_salted_hash($pass);
$dbadmin->update({
md5pass => undef,
saltedpass => $saltedpass,
});
}
}
$res = NGCP::Panel::Utils::Admin::perform_auth($c, $user, $pass);
} elsif($realm eq 'subscriber') {
my ($u, $d, $t) = split /\@/, $user;
if(defined $t) {

@ -7,6 +7,7 @@ BEGIN { extends 'Catalyst::Controller' }
use Scalar::Util qw(blessed);
use NGCP::Panel::Utils::DateTime qw();
use NGCP::Panel::Utils::Statistics qw();
use NGCP::Panel::Utils::Admin;
use DateTime qw();
use Time::HiRes qw();
use DateTime::Format::RFC3339 qw();
@ -153,8 +154,8 @@ sub auto :Private {
} else {
$c->log->debug("++++++ Root::auto API admin request with http auth");
my $realm = "api_admin_http";
my $res = $c->authenticate({}, $realm);
my ($user, $pass) = $c->req->headers->authorization_basic;
my $res = NGCP::Panel::Utils::Admin::perform_auth($c, $user, $pass);
unless($c->user_exists && $c->user->is_active) {
$c->user->logout if($c->user);
$c->log->debug("+++++ invalid api admin http login");

@ -92,6 +92,7 @@ sub _auth {
}, $auth->{password}));
die unless($usr_b64hash eq $db_b64hash);
die unless($admin->is_superuser || $admin->lawful_intercept);
} else {
my $md5admin = $c->model('DB')->resultset('admins')->search({
login => $auth->{username},

@ -1,7 +1,7 @@
package NGCP::Panel::Utils::Admin;
use Sipwise::Base;
use Crypt::Eksblowfish::Bcrypt qw/bcrypt_hash en_base64/;
use Crypt::Eksblowfish::Bcrypt qw/bcrypt_hash en_base64 de_base64/;
use Data::Entropy::Algorithms qw/rand_bits/;
sub get_bcrypt_cost {
@ -21,5 +21,68 @@ sub generate_salted_hash {
return $b64salt . '$' . $b64hash;
}
sub perform_auth {
my ($c, $user, $pass) = @_;
my $res;
my $dbadmin = $c->model('DB')->resultset('admins')->find({
login => $user,
is_active => 1,
});
if(defined $dbadmin && defined $dbadmin->saltedpass) {
$c->log->debug("login via bcrypt");
my ($db_b64salt, $db_b64hash) = split /\$/, $dbadmin->saltedpass;
my $salt = de_base64($db_b64salt);
my $usr_b64hash = en_base64(bcrypt_hash({
key_nul => 1,
cost => get_bcrypt_cost(),
salt => $salt,
}, $pass));
# fetch again to load user into session etc (otherwise we could
# simply compare the two hashes here :(
$res = $c->authenticate(
{
login => $user,
saltedpass => $db_b64salt . '$' . $usr_b64hash,
'dbix_class' => {
searchargs => [{
-and => [
login => $user,
is_active => 1,
],
}],
}
}, 'admin_bcrypt'
);
} elsif(defined $dbadmin) { # we already know if the username is wrong, no need to check again
# check md5 and migrate over to bcrypt on success
$c->log->debug("login via md5");
$res = $c->authenticate(
{
login => $user,
md5pass => $pass,
'dbix_class' => {
searchargs => [{
-and => [
login => $user,
is_active => 1,
],
}],
}
}, 'admin');
if($res) {
# login ok, time to move user to bcrypt hashing
$c->log->debug("migrating to bcrypt");
my $saltedpass = generate_salted_hash($pass);
$dbadmin->update({
md5pass => undef,
saltedpass => $saltedpass,
});
}
}
return $res;
}
1;

Loading…
Cancel
Save