TT#56411 honor use_session => 0 for bcrypt auth

Revert "Revert "TT#56411 honor use_session => 0 for bcrypt auth WIP""

This reverts commit 1cfc524f80.

Change-Id: I7eb0842bd61a4aaddbe50206fb974110ead8efb6
changes/12/28812/2
Rene Krenn 6 years ago
parent 1cfc524f80
commit 76b88062a1

@ -153,6 +153,38 @@ __PACKAGE__->config(
use_userdata_from_session => 1,
}
},
api_admin => {
credential => {
class => 'Password',
password_field => 'md5pass',
password_type => 'hashed',
password_hash_type => 'MD5'
},
store => {
class => 'DBIx::Class',
user_model => 'DB::admins',
id_field => 'id',
store_user_class => 'NGCP::Panel::Authentication::Store::RoleFromRealm',
#use_userdata_from_session => 1,
},
use_session => 0,
},
api_admin_bcrypt => {
credential => {
class => 'Password',
password_field => 'saltedpass',
# we handle the salt and hash management manually in Login.pm
password_type => 'clear',
},
store => {
class => 'DBIx::Class',
user_model => 'DB::admins',
id_field => 'id',
store_user_class => 'NGCP::Panel::Authentication::Store::RoleFromRealm',
#use_userdata_from_session => 1,
},
use_session => 0,
},
api_admin_cert => {
# TODO: should be NoPassword, but it's not available in our catalyst version yet
credential => {

@ -6,7 +6,7 @@ sub roles {
my ($self) = @_;
if ($self->auth_realm) {
for my $auth_type (qw/admin_bcrypt admin api_admin_cert api_admin_http/) {
for my $auth_type (qw/admin_bcrypt admin api_admin_cert api_admin_http api_admin api_admin_bcrypt/) {
if ($auth_type eq $self->auth_realm) {
$self->_user->is_superuser ? return "admin"
: return "reseller";

@ -12,7 +12,7 @@ use NGCP::Panel::Utils::Admin;
sub login_index :Path Form {
my ( $self, $c, $realm ) = @_;
$realm = 'subscriber'
$realm = 'subscriber'
unless($realm && $realm eq 'admin');
my $posted = ($c->req->method eq 'POST');
@ -30,7 +30,7 @@ sub login_index :Path Form {
$c->log->debug("*** Login::index user=$user, pass=****, realm=$realm");
my $res;
if($realm eq 'admin') {
$res = NGCP::Panel::Utils::Admin::perform_auth($c, $user, $pass);
$res = NGCP::Panel::Utils::Admin::perform_auth($c, $user, $pass, 'admin', 'admin_bcrypt');
} elsif($realm eq 'subscriber') {
my ($u, $d, $t) = split /\@/, $user;
if(defined $t) {
@ -52,12 +52,12 @@ sub login_index :Path Form {
});
$res = $c->authenticate(
{
webusername => $u,
webusername => $u,
webpassword => $pass,
'dbix_class' => {
resultset => $authrs
}
},
},
$realm);
}

@ -27,9 +27,12 @@ __PACKAGE__->config(namespace => '');
sub auto :Private {
my($self, $c) = @_;
my $is_api_request = 0;
$c->log->debug("Path: " . $c->request->path);
if ($c->request->path =~/^api\//i) {
$c->log->debug("Root::auto: enable cache");
NGCP::Panel::Form::dont_use_cache(0);
$is_api_request = 1;
} else {
$c->log->debug("Root::auto: disable cache");
NGCP::Panel::Form::dont_use_cache(1);
@ -43,31 +46,35 @@ sub auto :Private {
}
if(exists $c->installed_languages->{$c->request->params->{lang}} ||
$c->request->params->{lang} eq "i-default") {
$c->session->{lang} = $c->request->params->{lang};
$c->response->cookies->{ngcp_panel_lang} = { value => $c->request->params->{lang}, expires => '+3M', };
unless ($is_api_request) {
$c->session->{lang} = $c->request->params->{lang};
$c->response->cookies->{ngcp_panel_lang} = { value => $c->request->params->{lang}, expires => '+3M', };
}
$c->log->debug("Setting language to ". $c->request->params->{lang});
}
# clear form cache (they need to be properly re-translated)
NGCP::Panel::Form::clear_form_cache();
}
if (defined $c->session->{lang}) {
$c->languages([$c->session->{lang}, "i-default"]);
} elsif ( $c->req->cookie('ngcp_panel_lang') ) {
$c->session->{lang} = $c->req->cookie('ngcp_panel_lang')->value;
$c->languages([$c->session->{lang}, 'i-default']);
} else { # if language has not yet be set, set it from config or browser
if (defined $c->config->{appearance}{force_language}) {
$c->log->debug("lang set by config: " . $c->config->{appearance}{force_language});
$c->languages([$c->config->{appearance}{force_language}, 'i-default']);
} else {
$c->languages([ map { s/^en.*$/i-default/r } @{ $c->languages } ]);
unless ($is_api_request) {
if (defined $c->session->{lang}) {
$c->languages([$c->session->{lang}, "i-default"]);
} elsif ( $c->req->cookie('ngcp_panel_lang') ) {
$c->session->{lang} = $c->req->cookie('ngcp_panel_lang')->value;
$c->languages([$c->session->{lang}, 'i-default']);
} else { # if language has not yet be set, set it from config or browser
if (defined $c->config->{appearance}{force_language}) {
$c->log->debug("lang set by config: " . $c->config->{appearance}{force_language});
$c->languages([$c->config->{appearance}{force_language}, 'i-default']);
} else {
$c->languages([ map { s/^en.*$/i-default/r } @{ $c->languages } ]);
}
$c->session->{lang} = $c->language;
$c->log->debug("lang set by browser or config: " . $c->language);
}
$c->session->{lang} = $c->language;
$c->log->debug("lang set by browser or config: " . $c->language);
}
################################################### timezone retrieval
if ($c->user_exists) {
if (not $is_api_request and $c->user_exists) {
if ($c->session->{user_tz}) {
# nothing to do
} elsif ($c->user->roles eq 'admin') {
@ -110,142 +117,144 @@ sub auto :Private {
return 1;
}
unless($c->user_exists) {
if(index($c->controller->catalyst_component_name, 'NGCP::Panel::Controller::API') == 0) {
$c->log->debug("++++++ Root::auto unauthenticated API request");
my $ssl_dn = $c->request->env->{SSL_CLIENT_M_DN} // "";
my $ssl_sn = hex ($c->request->env->{SSL_CLIENT_M_SERIAL} // 0);
my $ngcp_api_realm = $c->request->env->{NGCP_API_REALM} // "";
if($ssl_sn) {
$c->log->debug("++++++ Root::auto API request with client auth sn '$ssl_sn'");
unless($ssl_dn eq "/CN=Sipwise NGCP API client certificate") {
$c->log->error("++++++ Root::auto API request with invalid client DN '$ssl_dn'");
$c->res->status(403);
$c->res->body(JSON::to_json({
message => "Invalid client certificate DN '$ssl_dn'",
code => 403,
}));
return;
}
#if($is_api_request or not $c->user_exists) {
if(index($c->controller->catalyst_component_name, 'NGCP::Panel::Controller::API') == 0) {
$c->log->debug("++++++ Root::auto unauthenticated API request");
my $ssl_dn = $c->request->env->{SSL_CLIENT_M_DN} // "";
my $ssl_sn = hex ($c->request->env->{SSL_CLIENT_M_SERIAL} // 0);
my $ngcp_api_realm = $c->request->env->{NGCP_API_REALM} // "";
if($ssl_sn) {
$c->log->debug("++++++ Root::auto API request with client auth sn '$ssl_sn'");
unless($ssl_dn eq "/CN=Sipwise NGCP API client certificate") {
$c->log->error("++++++ Root::auto API request with invalid client DN '$ssl_dn'");
$c->res->status(403);
$c->res->body(JSON::to_json({
message => "Invalid client certificate DN '$ssl_dn'",
code => 403,
}));
return;
}
my $res = $c->authenticate({
ssl_client_m_serial => $ssl_sn,
is_active => 1, # TODO: abused as password until NoPassword handler is available
}, 'api_admin_cert');
unless($c->user_exists) {
$c->log->warn("invalid api login from '".$c->req->address."'");
$c->detach(qw(API::Root invalid_user), [$ssl_sn]) unless $c->user_exists;
} else {
$c->log->debug("++++++ admin '".$c->user->login."' authenticated via api_admin_cert");
}
if($c->user->read_only && $c->req->method eq "POST" &&
$c->req->uri->path =~ m|^/api/admincerts/$|) {
$c->log->info("let read-only user '".$c->user->login."' generate admin cert for itself");
} elsif($c->user->read_only && !($c->req->method =~ /^(GET|HEAD|OPTIONS)$/)) {
$c->log->error("invalid method '".$c->req->method."' for read-only user '".$c->user->login."', rejecting");
$c->user->logout;
$c->log->error("++++ body data: " . $c->req->body_data);
$c->response->status(403);
$c->res->body(JSON::to_json({
message => "Invalid HTTP method for read-only user",
code => 403,
}));
return;
}
$self->api_apply_fake_time($c);
return 1;
} elsif ($c->req->headers->header("NGCP-UserAgent") &&
$c->req->headers->header("NGCP-UserAgent") eq "NGCP::API::Client") {
$c->log->debug("++++++ Root::auto API request with system auth");
my $realm = "api_admin_system";
my $res = $c->authenticate({}, $realm);
unless ($c->user_exists) {
$c->log->debug("+++++ invalid api admin system login");
$c->log->warn("invalid api system login from '".$c->req->address."'");
}
my $res = $c->authenticate({
ssl_client_m_serial => $ssl_sn,
is_active => 1, # TODO: abused as password until NoPassword handler is available
}, 'api_admin_cert');
unless($c->user_exists) {
$c->log->warn("invalid api login from '".$c->req->address."'");
$c->detach(qw(API::Root invalid_user), [$ssl_sn]) unless $c->user_exists;
} else {
$c->log->debug("++++++ admin '".$c->user->login."' authenticated via api_admin_cert");
}
if($c->user->read_only && $c->req->method eq "POST" &&
$c->req->uri->path =~ m|^/api/admincerts/$|) {
$c->log->info("let read-only user '".$c->user->login."' generate admin cert for itself");
} elsif($c->user->read_only && !($c->req->method =~ /^(GET|HEAD|OPTIONS)$/)) {
$c->log->error("invalid method '".$c->req->method."' for read-only user '".$c->user->login."', rejecting");
$c->user->logout;
$c->log->error("++++ body data: " . $c->req->body_data);
$c->response->status(403);
$c->res->body(JSON::to_json({
message => "Invalid HTTP method for read-only user",
code => 403,
}));
return;
}
$self->api_apply_fake_time($c);
return 1;
} elsif ($c->req->headers->header("NGCP-UserAgent") &&
$c->req->headers->header("NGCP-UserAgent") eq "NGCP::API::Client") {
$c->log->debug("++++++ Root::auto API request with system auth");
my $realm = "api_admin_system";
my $res = $c->authenticate({}, $realm);
unless ($c->user_exists) {
$c->log->debug("+++++ invalid api admin system login");
$c->log->warn("invalid api system login from '".$c->req->address."'");
}
$self->api_apply_fake_time($c);
return 1;
} elsif ($c->req->headers->header("Authorization") &&
$c->req->headers->header("Authorization") =~ m/^Bearer /) {
$c->log->debug("++++++ Root::auto API request with JWT");
my $realm = "api_subscriber_jwt";
my $res = $c->authenticate({}, $realm);
unless ($c->user_exists) {
$c->log->debug("+++++ invalid api subscriber JWT login");
# $c->log->warn("invalid api system login from '".$c->req->address."'");
}
$self->api_apply_fake_time($c);
return 1;
} elsif ($c->req->headers->header("Authorization") &&
$c->req->headers->header("Authorization") =~ m/^Bearer /) {
$c->log->debug("++++++ Root::auto API request with JWT");
my $realm = "api_subscriber_jwt";
my $res = $c->authenticate({}, $realm);
unless ($c->user_exists) {
$c->log->debug("+++++ invalid api subscriber JWT login");
# $c->log->warn("invalid api system login from '".$c->req->address."'");
}
$self->api_apply_fake_time($c);
return 1;
} elsif ($ngcp_api_realm eq "subscriber") {
$c->log->debug("++++++ Root::auto API subscriber request with http auth");
my $realm = "api_subscriber_http";
my ($username,$password) = $c->req->headers->authorization_basic;
my ($u,$d) = split(/\@/,$username);
if ($d) {
$c->req->headers->authorization_basic($u,$password);
}
my $res = $c->authenticate({}, $realm);
if($c->user_exists) {
$d //= $c->req->uri->host;
$c->log->debug("++++++ checking '".$c->user->domain->domain."' against '$d'");
if ($c->user->domain->domain ne $d) {
$c->user->logout;
$c->log->debug("+++++ invalid api subscriber http login by '$username' (domain check failed)");
$c->log->warn("invalid api http login from '".$c->req->address."' by '$username'");
my $r = $c->get_auth_realm($realm);
$r->credential->authorization_required_response($c, $r);
return;
}
$c->log->debug("++++++ subscriber '$username' authenticated via api_subscriber_http");
} else {
$c->user->logout if($c->user);
$c->log->debug("+++++ invalid api subscriber http login");
$self->api_apply_fake_time($c);
return 1;
} elsif ($ngcp_api_realm eq "subscriber") {
$c->log->debug("++++++ Root::auto API subscriber request with http auth");
my $realm = "api_subscriber_http";
my ($username,$password) = $c->req->headers->authorization_basic;
my ($u,$d) = split(/\@/,$username);
if ($d) {
$c->req->headers->authorization_basic($u,$password);
}
my $res = $c->authenticate({}, $realm);
if($c->user_exists) {
$d //= $c->req->uri->host;
$c->log->debug("++++++ checking '".$c->user->domain->domain."' against '$d'");
if ($c->user->domain->domain ne $d) {
$c->user->logout;
$c->log->debug("+++++ invalid api subscriber http login by '$username' (domain check failed)");
$c->log->warn("invalid api http login from '".$c->req->address."' by '$username'");
my $r = $c->get_auth_realm($realm);
$r->credential->authorization_required_response($c, $r);
return;
}
$self->api_apply_fake_time($c);
return 1;
$c->log->debug("++++++ subscriber '$username' authenticated via api_subscriber_http");
} else {
$c->log->debug("++++++ Root::auto API admin request with http auth");
my $realm = "api_admin_http";
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");
$c->log->warn("invalid api http login from '".$c->req->address."' by '$user'");
my $r = $c->get_auth_realm($realm);
$r->credential->authorization_required_response($c, $r);
return;
} else {
$c->log->debug("++++++ admin '".$c->user->login."' authenticated via api_admin_http");
}
if($c->user->read_only && $c->req->method eq "POST" &&
$c->req->uri->path =~ m|^/api/admincerts/$|) {
$c->log->info("let read-only user '".$c->user->login."' generate admin cert for itself");
} elsif($c->user->read_only && !($c->req->method =~ /^(GET|HEAD|OPTIONS)$/)) {
$c->log->error("invalid method '".$c->req->method."' for read-only user '".$c->user->login."', rejecting");
$c->user->logout;
$c->log->error("++++ body data: " . $c->req->body_data);
$c->response->status(403);
$c->res->body(JSON::to_json({
message => "Invalid HTTP method for read-only user",
code => 403,
}));
return;
}
$self->api_apply_fake_time($c);
return 1;
$c->user->logout if($c->user);
$c->log->debug("+++++ invalid api subscriber http login");
$c->log->warn("invalid api http login from '".$c->req->address."' by '$username'");
my $r = $c->get_auth_realm($realm);
$r->credential->authorization_required_response($c, $r);
return;
}
$self->api_apply_fake_time($c);
return 1;
} else {
$c->log->debug("++++++ Root::auto API admin request with http auth");
my ($user, $pass) = $c->req->headers->authorization_basic;
#$c->log->debug("user: " . $user . " pass: " . $pass);
my $res = NGCP::Panel::Utils::Admin::perform_auth($c, $user, $pass, "api_admin" , "api_admin_bcrypt");
if($res and $c->user_exists and $c->user->is_active) {
$c->log->debug("++++++ admin '".$c->user->login."' authenticated via api_admin_http");
} else {
my $realm = 'api_admin_http';
$c->user->logout if($c->user);
$c->log->debug("+++++ invalid api admin http login");
$c->log->warn("invalid api http login from '".$c->req->address."' by '$user'");
my $r = $c->get_auth_realm($realm);
$r->credential->authorization_required_response($c, $r);
return;
}
if($c->user->read_only && $c->req->method eq "POST" &&
$c->req->uri->path =~ m|^/api/admincerts/$|) {
$c->log->info("let read-only user '".$c->user->login."' generate admin cert for itself");
} elsif($c->user->read_only && !($c->req->method =~ /^(GET|HEAD|OPTIONS)$/)) {
$c->log->error("invalid method '".$c->req->method."' for read-only user '".$c->user->login."', rejecting");
$c->user->logout;
$c->log->error("++++ body data: " . $c->req->body_data);
$c->response->status(403);
$c->res->body(JSON::to_json({
message => "Invalid HTTP method for read-only user",
code => 403,
}));
return;
}
$self->api_apply_fake_time($c);
#$c->log->debug("return 1");
return 1;
}
} elsif (not $c->user_exists) {
# don't redirect to login page for ajax uris
if($c->request->path =~ /\/ajax$/) {

@ -29,13 +29,14 @@ sub generate_salted_hash {
}
sub perform_auth {
my ($c, $user, $pass) = @_;
my ($c, $user, $pass, $realm, $bcrypt_realm) = @_;
my $res;
my $dbadmin = $c->model('DB')->resultset('admins')->find({
my $dbadmin;
$dbadmin = $c->model('DB')->resultset('admins')->find({
login => $user,
is_active => 1,
});
}) if $user;
if(defined $dbadmin && defined $dbadmin->saltedpass) {
$c->log->debug("login via bcrypt");
my ($db_b64salt, $db_b64hash) = split /\$/, $dbadmin->saltedpass;
@ -59,7 +60,7 @@ sub perform_auth {
],
}],
}
}, 'admin_bcrypt'
}, $bcrypt_realm
);
} elsif(defined $dbadmin) { # we already know if the username is wrong, no need to check again
@ -77,7 +78,7 @@ sub perform_auth {
],
}],
}
}, 'admin');
}, $realm);
if($res) {
# login ok, time to move user to bcrypt hashing
@ -107,7 +108,7 @@ sub generate_client_cert {
return;
}
try {
$admin->update({
$admin->update({
ssl_client_m_serial => $serial,
ssl_client_certificate => undef, # not used anymore, clear it just in case
});
@ -224,7 +225,7 @@ sub toggle_openvpn {
$error = cmd($c, undef, $systemctl_cmd, 'enable', $openvpn_service);
if (!$error) {
my $status_enabled = check_openvpn_status($c, {
no_check_availability => 1,
no_check_availability => 1,
check_status => 'enabled',
},
);
@ -234,7 +235,7 @@ sub toggle_openvpn {
$error = cmd($c, undef, $systemctl_cmd, 'start', $openvpn_service);
if (!$error) {
$status_out = check_openvpn_status($c, {
no_check_availability => 1,
no_check_availability => 1,
},
);
if ($status_out->{active}) {
@ -255,7 +256,7 @@ sub toggle_openvpn {
}
if (!$error) {
$status_out = check_openvpn_status($c, {
no_check_availability => 1,
no_check_availability => 1,
},
);
if (!$status_out->{active}) {

@ -46,7 +46,7 @@ sub get_log_params {
if ($c->user_exists) {
if ($c->user->roles eq 'admin' || $c->user->roles eq 'reseller') {
$r_user = $c->user->login;
} else {
} elsif ($c->user->roles eq 'subscriberadmin' || $c->user->roles eq 'subscriber') {
$r_user = $c->user->webusername . '@' . $c->user->domain->domain;
}
}
@ -166,7 +166,7 @@ sub error {
$msg = "$desc ($error)";
$usr_text = "$desc ($dup)";
}
elsif (my ($excerpt) = $error =~ /(Column \S+ cannot be null)/)
elsif (my ($excerpt) = $error =~ /(Column \S+ cannot be null)/)
{
$msg = "$desc ($error)";
$usr_text = "$desc ($excerpt)";
@ -244,7 +244,7 @@ sub info {
#flash is on by default
if (!defined $params{flash} || $params{flash} ) {
$c->flash(messages => [{ type => $usr_type, text => $usr_text }]);
}
}
if ($params{stash} ) {
my $messages = $c->stash->{messages} // [];
push @$messages, { type => $usr_type, text => $usr_text };

Loading…
Cancel
Save