diff --git a/lib/AccountManager/App.pm b/lib/AccountManager/App.pm index 1ca0bfe538a6a423e0fb1004b65d88e8ae827a58..90028ae077d72e94bbb292113107189f52ab1f70 100644 --- a/lib/AccountManager/App.pm +++ b/lib/AccountManager/App.pm @@ -169,13 +169,9 @@ sub run { my $method = $actions{$action}; $self->$method(); } else { - ## unknown action - $self->{logger}->error( "Unknown action '$action'"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "Unknown action '$action'" ] - } + $self->abort( + logs => "Unknown action '$action'", + user => "Unknown action '$action'" ); } @@ -224,6 +220,20 @@ sub respond { exit 0; } +sub abort { + my $self = shift; + my %args = @_; + + $self->{logger}->error($args{log}) if $args{log}; + + $self->respond( + template => 'errors.tt2.html', + data => { + errors => [ $args{user} ] + } + ); +} + sub req_start { my ($self) = @_; @@ -256,43 +266,27 @@ sub req_select_sp { my $federation = $self->{in}->{federation}; - if (!$federation) { - $self->{logger}->error("Missing parameter: federation"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_federation" ] - } - ); - } + $self->abort( + log => "Missing parameter: federation", + user => "missing_federation" + ) if !$federation; my $file = $self->{configuration}->{federations}->{$federation}; - if (!$file) { - $self->{logger}->error("Incorrect parameter: federation"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "invalid_federation" ] - } - ); - } + $self->abort( + log => "Incorrect parameter: federation", + user => "invalid_federation" + ) if !$file; my $metadata; - eval { $metadata = AccountManager::Metadata->new( file => $file ); }; - if ($EVAL_ERROR) { - $self->{logger}->error("Failed to load federation metadata: $EVAL_ERROR"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + $self->abort( + log => "Failed to load federation metadata: $EVAL_ERROR", + user => "internal" + ) if $EVAL_ERROR; $self->respond( template => 'select_sp.tt2.html', @@ -308,47 +302,25 @@ sub req_select_email { my ($self) = @_; my $federation = $self->{in}->{federation}; - - if (!$federation) { - $self->{logger}->error("Missing parameter: federation"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_federation" ] - } - ); - } + $self->abort( + log => "Missing parameter: federation", + user => "missing_federation" + ) if !$federation; my $file = $self->{configuration}->{federations}->{$federation}; - if (!$file) { - $self->{logger}->error("Incorrect parameter: federation"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "invalid_federation" ] - } - ); - } - - if (! $self->{in}->{entityid}) { - $self->{logger}->error("Missing parameter: entityid"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_entityid" ] - } - ); - } - - if ($self->{in}->{entityid} !~ $entity_id_pattern) { - $self->{logger}->error("Incorrect parameter format: entityid"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "format_entityid" ] - } - ); - } + $self->abort( + log => "Incorrect parameter: federation", + user => "invalid_federation" + ) if !$file; + + $self->abort( + log => "Missing parameter: entityid", + user => "missing_entityid" + ) if !$self->{in}->{entityid}; + $self->abort( + log => "Incorrect parameter format: entityid", + user => "format_entityid" + ) if $self->{in}->{entityid} !~ $entity_id_pattern; # Create a persistent service provider object my $sp = AccountManager::Service->new( @@ -367,29 +339,17 @@ sub req_select_email { file => $file ); }; - if ($EVAL_ERROR) { - $self->{logger}->error("Failed to load federation metadata: $EVAL_ERROR"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + $self->abort( + log => "Failed to load federation metadata: $EVAL_ERROR", + user => "internal" + ) if $EVAL_ERROR; my $entities = $metadata->parse(id => $self->{in}->{entityid}); - if (!@$entities) { - $self->{logger}->errorf( - "No such SP '%s' in metadata", $self->{in}->{entityid} - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "no_such_entity" ] - } - ); - } my $entity = $entities->[0]; + $self->abort( + log => sprintf("No such SP '%s' in metadata", $self->{in}->{entityid}), + user => "no_such_entity" + ) if !$entity; # complete persistent object $sp->displayname($entity->{display_name}); @@ -397,21 +357,15 @@ sub req_select_email { if $entity->{contacts}; # save in DB - unless ($sp->save()) { - $self->{logger}->error("Failed to save service provider object"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + $self->abort( + log => "Failed to save service provider object", + user => "internal" + ) if !$sp->save(); } # override metadata contacts if needed - my $id = $self->{in}->{entityid}; my $contacts = - $self->{configuration}->{$id}->{contacts} || + $self->{configuration}->{$self->{in}->{entityid}}->{contacts} || $self->{configuration}->{service}->{contacts}; if ($contacts) { if ($contacts =~ /^\+(.+)/) { @@ -429,7 +383,7 @@ sub req_select_email { action => 'select_email', federation => $federation, sp => $sp, - entityid => $sp->entityid(), + entityid => $self->{in}->{entityid}, } ); } @@ -438,67 +392,43 @@ sub req_complete_challenge { my ($self) = @_; my $federation = $self->{in}->{federation}; - - if (!$federation) { - $self->{logger}->error("Missing parameter: federation"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_federation" ] - } - ); - } + $self->abort( + log => "Missing parameter: federation", + user => "missing_federation" + ) if !$federation; my $file = $self->{configuration}->{federations}->{$federation}; - if (!$file) { - $self->{logger}->error("Incorrect parameter: federation"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "invalid_federation" ] - } - ); - } - - unless ($self->{in}->{entityid}) { - $self->{logger}->error("Missing parameter entityid"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_entityid" ] - } - ); - } - - unless ($self->{in}->{email}) { - $self->{logger}->error("Missing parameter email"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_email" ] - } - ); - } + $self->abort( + log => "Incorrect parameter: federation", + user => "invalid_federation" + ) if !$file; + + $self->abort( + log => "Missing parameter: entityid", + user => "missing_entityid" + ) if !$self->{in}->{entityid}; + $self->abort( + log => "Incorrect parameter format: entityid", + user => "format_entityid" + ) if $self->{in}->{entityid} !~ $entity_id_pattern; + + $self->abort( + log => "Missing parameter: email", + user => "missing_email" + ) if !$self->{in}->{email}; my $provider = AccountManager::Service->new( db => $self->{db}, entityid => $self->{in}->{entityid}, ); - - unless ($provider->load(speculative => 1)) { - $self->{logger}->errorf("No such SP '%s' in database", $self->{in}->{entityid}); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "no_such_entity" ] - } - ); - } + $self->abort( + log => sprintf("No such SP '%s' in database", $self->{in}->{entityid}), + user => "no_such_entity" + ) if !$provider->load(speculative => 1); # override metadata contacts if needed - my $entity = $self->{in}->{entityid}; my $contacts = - $self->{configuration}->{$entity}->{contacts} || + $self->{configuration}->{$self->{in}->{entityid}}->{contacts} || $self->{configuration}->{service}->{contacts}; if ($contacts) { if ($contacts =~ /^\+(.+)/) { @@ -511,41 +441,27 @@ sub req_complete_challenge { } ## Check that email is a known contact for this SP - unless ($provider->is_contact($self->{in}->{email})) - { - $self->{logger}->errorf( + $self->abort( + log => sprintf( "Requested a token for %s for an unautorized address '%s'", - $self->{in}->{entityid}, + $self->{in}->entityid, $self->{in}->{email} - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + ), + user => "internal", + ) if !$provider->is_contact($self->{in}->{email}); # delete any previous token for the same email/service couple my $old_token = AccountManager::Token->new( db => $self->{db}, email_address => $self->{in}->{email}, - sp_entityid => $self->{in}->{entityid} + sp_entityid => $self->{in}->{entityid}, ); if ($old_token->load(speculative => 1)) { - unless ($old_token->delete()) { - $self->{logger}->errorf( - "Failed to delete previous authentication token with ID %s", - $old_token->id() - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + $self->abort( + log => sprintf("Failed to delete previous authentication token with ID %s", $old_token->id()), + user => "internal" + ) if !$old_token->delete(); } # compute a new token @@ -561,15 +477,10 @@ sub req_complete_challenge { token => AccountManager::Tools::generate_secret(20) ); - unless ($token->save()) { - $self->{logger}->error("Failed to save authentication token"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + $self->abort( + log => "Failed to save service authentication token", + user => "internal" + ) if !$token->save(); # build content my $tt2 = Template->new({ @@ -635,15 +546,10 @@ sub req_complete_challenge { eval { Email::Sender::Simple->send($email); }; - if ($EVAL_ERROR) { - $self->{logger}->errorf("Mail notification error: %s", $EVAL_ERROR); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "mail_notification_failure" ] - } - ); - } + $self->abort( + log => "Mail notification error: $EVAL_ERROR", + user => "mail_notification_failure" + ) if $EVAL_ERROR; $self->{logger}->infof( "Token send to %s for entityid=%s;token=%s", @@ -666,68 +572,47 @@ sub req_complete_challenge { sub req_create_accounts { my ($self) = @_; - unless ($self->{in}->{entityid}) { - $self->{logger}->error("Missing parameter entityid"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_entityid" ] - } - ); - } - - unless ($self->{in}->{token}) { - $self->{logger}->error("Missing parameter token"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_token" ] - } - ); - } - - unless ($self->{in}->{email}) { - $self->{logger}->error("Missing parameter email"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_email" ] - } - ); - } + $self->abort( + log => "Missing parameter: entityid", + user => "missing_entityid" + ) if !$self->{in}->{entityid}; + $self->abort( + log => "Incorrect parameter format: entityid", + user => "format_entityid" + ) if $self->{in}->{entityid} !~ $entity_id_pattern; + + $self->abort( + log => "Missing parameter: token", + user => "missing_token" + ) if !$self->{in}->{token}; + + $self->abort( + log => "Missing parameter: email", + user => "missing_email" + ) if !$self->{in}->{email}; my $token = AccountManager::Token->new( db => $self->{db}, token => $self->{in}->{token} ); - if (! $token->load(speculative => 1)) { - $self->{logger}->errorf( + $self->abort( + log => sprintf( "Failed to validate authentication token %s for entityid %s", $self->{in}->{token}, $self->{in}->{entityid} - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "wrong_token" ] - } - ); - } + ), + user => "wrong_token" + ) if !$token->load(speculative => 1); - if (! $token->sp_entityid() eq $self->{in}->{entityid}) { - $self->{logger}->errorf( + $self->abort( + log => sprintf( "Authentication token %s cannot be used for SP with entityid %s", $self->{in}->{token}, $self->{in}->{entityid} - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "wrong_token_for_sp" ] - } - ); - } + ), + user => "wrong_token_for_sp" + ) if $token->sp_entityid() ne $self->{in}->{entityid}; ## delete the token unless ($token->delete()) { @@ -758,15 +643,10 @@ sub req_create_accounts { token => AccountManager::Tools::generate_secret(20) ); - unless ($download_token->save()) { - $self->{logger}->error("Failed to save authentication token"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "internal" ] - } - ); - } + $self->abort( + log => "Failed to save download authentication token", + user => "internal" + ) if !$download_token->save(); my $key = AccountManager::Tools::generate_secret(10); @@ -788,18 +668,13 @@ sub req_create_accounts { push @accounts, $account; } - unless (@accounts) { - $self->{logger}->errorf( + $self->abort( + log => sprintf( "Failed to create test accounts for SP with entityid %s", $self->{in}->{entityid} - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "accounts_creation_failure" ] - } - ); - } + ), + user => "accounts_creation_failure" + ) if !@accounts; ## Update simpleSAMLphp configuration to enable test accounts my $accounts = AccountManager::Account::Manager->get_accounts( @@ -813,18 +688,13 @@ sub req_create_accounts { $accounts ); }; - if ($EVAL_ERROR) { - $self->{logger}->errorf( + $self->abort( + log => sprintf( "Failed to create simpleSAMLphp configuration file: %s", $EVAL_ERROR - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "accounts_creation_failed" ] - } - ); - } + ), + user => "accounts_creation_failed" + ) if $EVAL_ERROR; $self->{logger}->infof( "Token validated for entityid=%s;token=%s", @@ -849,67 +719,47 @@ sub req_create_accounts { sub req_download_accounts { my ($self) = @_; - unless ($self->{in}->{entityid}) { - $self->{logger}->error("Missing parameter entityid"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_entityid" ] - } - ); - } - - unless ($self->{in}->{token}) { - $self->{logger}->error("Missing parameter token"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_token" ] - } - ); - } - - unless ($self->{in}->{key}) { - $self->{logger}->error("Missing parameter key"); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "missing_key" ] - } - ); - } + $self->abort( + log => "Missing parameter: entityid", + user => "missing_entityid" + ) if !$self->{in}->{entityid}; + $self->abort( + log => "Incorrect parameter format: entityid", + user => "format_entityid" + ) if $self->{in}->{entityid} !~ $entity_id_pattern; + + $self->abort( + log => "Missing parameter: token", + user => "missing_token" + ) if !$self->{in}->{token}; + + $self->abort( + log => "Missing parameter: key", + user => "missing_key" + ) if !$self->{in}->{key}; my $token = AccountManager::Token->new( db => $self->{db}, token => $self->{in}->{token} ); - if (! $token->load(speculative => 1)) { - $self->{logger}->errorf( - "Non-existing authentication token %s", + $self->abort( + log => sprintf( + "Failed to validate authentication token %s for entityid %s", $self->{in}->{token}, - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "wrong_token" ] - } - ); - } + $self->{in}->{entityid} + ), + user => "wrong_token" + ) if !$token->load(speculative => 1); - if (! $token->sp_entityid() eq $self->{in}->{entityid}) { - $self->{logger}->errorf( - "Authentication token %s cannot be used for SP %s", + $self->abort( + log => sprintf( + "Authentication token %s cannot be used for SP with entityid %s", $self->{in}->{token}, $self->{in}->{entityid} - ); - $self->respond( - template => 'errors.tt2.html', - data => { - errors => [ "wrong_token_for_sp" ] - } - ); - } + ), + user => "wrong_token_for_sp" + ) if $token->sp_entityid() ne $self->{in}->{entityid}; # delete the token unless ($token->delete()) {