diff --git a/lib/AccountManager/App.pm b/lib/AccountManager/App.pm index 90028ae077d72e94bbb292113107189f52ab1f70..4adcaf07427c74bc1d508639e1c02dc1986ea7f0 100644 --- a/lib/AccountManager/App.pm +++ b/lib/AccountManager/App.pm @@ -142,28 +142,8 @@ sub new { sub run { my ($self) = @_; - # process input parameters - my %parameters = $self->{cgi}->Vars(); - - foreach my $parameter (keys %parameters) { - - # cleanup - $parameters{$parameter} =~ s/\r//g; # remove &0D char - $parameters{$parameter} =~ s/\s+$//; # remove trailing spaces - $parameters{$parameter} =~ s/^\s+//; # remove leading spaces - - # register needed parameters - $self->{in} = { - email => $parameters{email}, - entityid => $parameters{entityid}, - token => $parameters{token}, - key => $parameters{key}, - federation => $parameters{federation}, - }; - } - # process requested action - my $action = $parameters{action} || 'home'; + my $action = $self->{cgi}->param('action') || 'home'; if ($actions{$action}) { $self->{logger}->debug("Processing action '$action'"); my $method = $actions{$action}; @@ -235,12 +215,11 @@ sub abort { } sub req_start { - my ($self) = @_; + my ($self, %args) = @_; my @federations = keys %{$self->{configuration}->{federations}}; if (@federations == 1) { - $self->{in}->{federation} = $federations[0]; - $self->req_select_sp(); + $self->req_select_sp(federation => $federations[0]); } else { $self->req_select_federation(); } @@ -248,7 +227,7 @@ sub req_start { sub req_select_federation { - my ($self) = @_; + my ($self, %args) = @_; my @federations = keys %{$self->{configuration}->{federations}}; @@ -262,10 +241,9 @@ sub req_select_federation { } sub req_select_sp { - my ($self) = @_; - - my $federation = $self->{in}->{federation}; + my ($self, %args) = @_; + my $federation = $args{federation} || $self->{cgi}->param('federation'); $self->abort( log => "Missing parameter: federation", user => "missing_federation" @@ -299,9 +277,9 @@ sub req_select_sp { } sub req_select_email { - my ($self) = @_; + my ($self, %args) = @_; - my $federation = $self->{in}->{federation}; + my $federation = $self->{cgi}->param('federation'); $self->abort( log => "Missing parameter: federation", user => "missing_federation" @@ -313,19 +291,20 @@ sub req_select_email { user => "invalid_federation" ) if !$file; + my $entityid = $self->{cgi}->param('entityid'); $self->abort( log => "Missing parameter: entityid", user => "missing_entityid" - ) if !$self->{in}->{entityid}; + ) if !$entityid; $self->abort( log => "Incorrect parameter format: entityid", user => "format_entityid" - ) if $self->{in}->{entityid} !~ $entity_id_pattern; + ) if $entityid !~ $entity_id_pattern; # Create a persistent service provider object my $sp = AccountManager::Service->new( db => $self->{db}, - entityid => $self->{in}->{entityid} + entityid => $entityid ); if ($sp->load(speculative => 1)) { @@ -344,10 +323,10 @@ sub req_select_email { user => "internal" ) if $EVAL_ERROR; - my $entities = $metadata->parse(id => $self->{in}->{entityid}); + my $entities = $metadata->parse(id => $entityid); my $entity = $entities->[0]; $self->abort( - log => sprintf("No such SP '%s' in metadata", $self->{in}->{entityid}), + log => sprintf("No such SP '%s' in metadata", $entityid), user => "no_such_entity" ) if !$entity; @@ -365,7 +344,7 @@ sub req_select_email { # override metadata contacts if needed my $contacts = - $self->{configuration}->{$self->{in}->{entityid}}->{contacts} || + $self->{configuration}->{$entityid}->{contacts} || $self->{configuration}->{service}->{contacts}; if ($contacts) { if ($contacts =~ /^\+(.+)/) { @@ -383,15 +362,15 @@ sub req_select_email { action => 'select_email', federation => $federation, sp => $sp, - entityid => $self->{in}->{entityid}, + entityid => $entityid, } ); } sub req_complete_challenge { - my ($self) = @_; + my ($self, %args) = @_; - my $federation = $self->{in}->{federation}; + my $federation = $self->{cgi}->param('federation'); $self->abort( log => "Missing parameter: federation", user => "missing_federation" @@ -403,32 +382,34 @@ sub req_complete_challenge { user => "invalid_federation" ) if !$file; + my $entityid = $self->{cgi}->param('entityid'); $self->abort( log => "Missing parameter: entityid", user => "missing_entityid" - ) if !$self->{in}->{entityid}; + ) if !$entityid; $self->abort( log => "Incorrect parameter format: entityid", user => "format_entityid" - ) if $self->{in}->{entityid} !~ $entity_id_pattern; + ) if $entityid !~ $entity_id_pattern; + my $email = $self->{cgi}->param('email'); $self->abort( log => "Missing parameter: email", user => "missing_email" - ) if !$self->{in}->{email}; + ) if !$email; my $provider = AccountManager::Service->new( db => $self->{db}, - entityid => $self->{in}->{entityid}, + entityid => $entityid, ); $self->abort( - log => sprintf("No such SP '%s' in database", $self->{in}->{entityid}), + log => sprintf("No such SP '%s' in database", $entityid), user => "no_such_entity" ) if !$provider->load(speculative => 1); # override metadata contacts if needed my $contacts = - $self->{configuration}->{$self->{in}->{entityid}}->{contacts} || + $self->{configuration}->{$entityid}->{contacts} || $self->{configuration}->{service}->{contacts}; if ($contacts) { if ($contacts =~ /^\+(.+)/) { @@ -444,17 +425,17 @@ sub req_complete_challenge { $self->abort( log => sprintf( "Requested a token for %s for an unautorized address '%s'", - $self->{in}->entityid, - $self->{in}->{email} + $entityid, + $email ), user => "internal", - ) if !$provider->is_contact($self->{in}->{email}); + ) if !$provider->is_contact($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}, + email_address => $email, + sp_entityid => $entityid, ); if ($old_token->load(speculative => 1)) { @@ -470,8 +451,8 @@ sub req_complete_challenge { $self->{configuration}->{service}->{tokens_validity_period}; my $token = AccountManager::Token->new( db => $self->{db}, - email_address => $self->{in}->{email}, - sp_entityid => $self->{in}->{entityid}, + email_address => $email, + sp_entityid => $entityid, creation_date => DateTime->now(), expiration_date => DateTime->now()->add(hours => $validity_period), token => AccountManager::Tools::generate_secret(20) @@ -495,15 +476,15 @@ sub req_complete_challenge { version => $self->{configuration}->{app}->{version}, }, sourceip => $ENV{REMOTE_ADDR}, - to => $self->{in}->{email}, - entityid => $self->{in}->{entityid}, + to => $email, + entityid => $entityid, token => $token->token(), challenge_url => sprintf( '%s&action=complete_challenge&federation=%s&entity=%s&email=%s', $self->{configuration}->{app}->{url}, - $self->{in}->{federation}, - $self->{in}->{entityid}, - $self->{in}->{email}, + $federation, + $entityid, + $email, ), lh => $self->{lh}, }; @@ -516,10 +497,10 @@ sub req_complete_challenge { eval "require Email::MIME"; eval "require Email::Sender::Simple"; - my $email = Email::MIME->create( + my $message = Email::MIME->create( header_str => [ 'From' => sprintf('eduGAIN Access Check <%s>', $self->{configuration}->{mailer}->{from}), - 'To' => $self->{in}->{email}, + 'To' => $email, 'Subject' => sprintf('[eduGAIN Access Check] %s', $self->{lh}->maketext("Test accounts request")), 'Content-Type' => 'multipart/alternative' ], @@ -544,7 +525,7 @@ sub req_complete_challenge { ); eval { - Email::Sender::Simple->send($email); + Email::Sender::Simple->send($message); }; $self->abort( log => "Mail notification error: $EVAL_ERROR", @@ -553,8 +534,8 @@ sub req_complete_challenge { $self->{logger}->infof( "Token send to %s for entityid=%s;token=%s", - $self->{in}->{email}, - $self->{in}->{entityid}, + $email, + $entityid, $token->token(), ); @@ -563,44 +544,47 @@ sub req_complete_challenge { data => { action => 'complete_challenge', federation => $federation, - entityid => $self->{in}->{entityid}, - email => $self->{in}->{email}, + entityid => $entityid, + email => $email, } ); } sub req_create_accounts { - my ($self) = @_; + my ($self, %args) = @_; + my $entityid = $self->{cgi}->param('entityid'); $self->abort( log => "Missing parameter: entityid", user => "missing_entityid" - ) if !$self->{in}->{entityid}; + ) if !$entityid; $self->abort( log => "Incorrect parameter format: entityid", user => "format_entityid" - ) if $self->{in}->{entityid} !~ $entity_id_pattern; + ) if $entityid !~ $entity_id_pattern; + my $token_secret = $self->{cgi}->param('token'); $self->abort( log => "Missing parameter: token", user => "missing_token" - ) if !$self->{in}->{token}; + ) if !$token_secret; + my $email = $self->{cgi}->param('email'); $self->abort( log => "Missing parameter: email", user => "missing_email" - ) if !$self->{in}->{email}; + ) if !$email; my $token = AccountManager::Token->new( db => $self->{db}, - token => $self->{in}->{token} + token => $token_secret ); $self->abort( log => sprintf( "Failed to validate authentication token %s for entityid %s", - $self->{in}->{token}, - $self->{in}->{entityid} + $token_secret, + $entityid ), user => "wrong_token" ) if !$token->load(speculative => 1); @@ -608,36 +592,35 @@ sub req_create_accounts { $self->abort( log => sprintf( "Authentication token %s cannot be used for SP with entityid %s", - $self->{in}->{token}, - $self->{in}->{entityid} + $token_secret, + $entityid ), user => "wrong_token_for_sp" - ) if $token->sp_entityid() ne $self->{in}->{entityid}; + ) if $token->sp_entityid() ne $entityid; ## delete the token unless ($token->delete()) { $self->{logger}->errorf( "Failed to delete authentication token %s", - $self->{in}->{token} + $token_secret ); } ## create test accounts my @accounts; - my $entity = $self->{in}->{entityid}; my $profiles = - $self->{configuration}->{$entity}->{account_profiles} || + $self->{configuration}->{$entityid}->{account_profiles} || $self->{configuration}->{service}->{account_profiles}; my $validity_period = - $self->{configuration}->{$entity}->{account_validity_period} || + $self->{configuration}->{$entityid}->{account_validity_period} || $self->{configuration}->{service}->{account_validity_period}; eval "require DateTime"; my $download_token = AccountManager::Token->new( db => $self->{db}, - email_address => $self->{in}->{email}, - sp_entityid => $self->{in}->{entityid}, + email_address => $email, + sp_entityid => $entityid, creation_date => DateTime->now(), expiration_date => DateTime->now()->add(hours => $validity_period), token => AccountManager::Tools::generate_secret(20) @@ -655,7 +638,7 @@ sub req_create_accounts { my $account = AccountManager::Account->new( db => $self->{db}, profile => $profile, - sp_entityid => $entity, + sp_entityid => $entityid, scope => $self->{configuration}->{idp}->{scope}, password => $password, password_crypt => AccountManager::Tools::encrypt($password, $key), @@ -671,7 +654,7 @@ sub req_create_accounts { $self->abort( log => sprintf( "Failed to create test accounts for SP with entityid %s", - $self->{in}->{entityid} + $entityid ), user => "accounts_creation_failure" ) if !@accounts; @@ -698,8 +681,8 @@ sub req_create_accounts { $self->{logger}->infof( "Token validated for entityid=%s;token=%s", - $self->{in}->{entityid}, - $self->{in}->{token} + $entityid, + $token_secret ); $self->respond( @@ -707,8 +690,8 @@ sub req_create_accounts { data => { action => 'create_accounts', accounts => \@accounts, - entityid => $self->{in}->{entityid}, - email => $self->{in}->{email}, + entityid => $entityid, + email => $email, key => $key, token => $download_token->token(), days => $validity_period, @@ -719,35 +702,38 @@ sub req_create_accounts { sub req_download_accounts { my ($self) = @_; + my $entityid = $self->{cgi}->param('entityid'); $self->abort( log => "Missing parameter: entityid", user => "missing_entityid" - ) if !$self->{in}->{entityid}; + ) if !$entityid; $self->abort( log => "Incorrect parameter format: entityid", user => "format_entityid" - ) if $self->{in}->{entityid} !~ $entity_id_pattern; + ) if $entityid !~ $entity_id_pattern; + my $token_secret = $self->{cgi}->param('token'); $self->abort( log => "Missing parameter: token", user => "missing_token" - ) if !$self->{in}->{token}; + ) if !$token_secret; + my $key = $self->{cgi}->param('key'); $self->abort( log => "Missing parameter: key", user => "missing_key" - ) if !$self->{in}->{key}; + ) if !$key; my $token = AccountManager::Token->new( db => $self->{db}, - token => $self->{in}->{token} + token => $token_secret ); $self->abort( log => sprintf( "Failed to validate authentication token %s for entityid %s", - $self->{in}->{token}, - $self->{in}->{entityid} + $token_secret, + $entityid ), user => "wrong_token" ) if !$token->load(speculative => 1); @@ -755,8 +741,8 @@ sub req_download_accounts { $self->abort( log => sprintf( "Authentication token %s cannot be used for SP with entityid %s", - $self->{in}->{token}, - $self->{in}->{entityid} + $token_secret, + $entityid ), user => "wrong_token_for_sp" ) if $token->sp_entityid() ne $self->{in}->{entityid}; @@ -765,7 +751,7 @@ sub req_download_accounts { unless ($token->delete()) { $self->{logger}->errorf( "Failed to delete authentication token %s", - $self->{in}->{token} + $token_secret ); }