Mercurial > hg > soundsoftware-site
changeset 732:897bc2b63bfe feature_318
Overhaul SoundSoftware authentication manager to handle HTTPS redirects itself and also to avoid info leakage for nonexistent projects
author | Chris Cannam |
---|---|
date | Fri, 04 Nov 2011 10:28:40 +0000 |
parents | 7c7ef64e68da |
children | c7a731db96e5 |
files | extra/soundsoftware/SoundSoftware.pm |
diffstat | 1 files changed, 78 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/extra/soundsoftware/SoundSoftware.pm Mon Oct 17 17:03:46 2011 +0100 +++ b/extra/soundsoftware/SoundSoftware.pm Fri Nov 04 10:28:40 2011 +0000 @@ -110,6 +110,11 @@ req_override => OR_AUTHCFG, args_how => TAKE1, }, + { + name => 'SoundSoftwareSslRequired', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, ); sub SoundSoftwareDSN { @@ -143,6 +148,8 @@ } } +sub SoundSoftwareSslRequired { set_val('SoundSoftwareSslRequired', @_); } + sub trim { my $string = shift; $string =~ s/\s{2,}/ /g; @@ -184,33 +191,75 @@ my $project_id = get_project_identifier($dbh, $r); - if (!defined $read_only_methods{$method}) { - print STDERR "SoundSoftware.pm:$$: Method is not read-only\n"; - if (project_repo_is_readonly($dbh, $project_id, $r)) { - print STDERR "SoundSoftware.pm:$$: Project repo is read-only, refusing access\n"; - return FORBIDDEN; - } else { - print STDERR "SoundSoftware.pm:$$: Project repo is read-write, authentication handler required\n"; - return OK; - } - } + # We want to delegate most of the work to the authentication + # handler (to ensure that user is asked to login even for + # nonexistent projects -- so they can't tell whether a private + # project exists or not without authenticating). So + # + # * if the project is public + # - if the method is read-only + # + set handler to OK, no auth needed + # - if the method is not read-only + # + if the repo is read-only, return forbidden + # + else require auth + # * if the project is not public or does not exist + # + require auth + # + # If we are requiring auth and are not currently https, and + # https is required, then we must return a redirect to https + # instead of an OK. my $status = get_project_status($dbh, $project_id, $r); + my $readonly = project_repo_is_readonly($dbh, $project_id, $r); $dbh->disconnect(); undef $dbh; - if ($status == 0) { # nonexistent - print STDERR "SoundSoftware.pm:$$: Project does not exist, refusing access\n"; - return FORBIDDEN; - } elsif ($status == 1) { # public - print STDERR "SoundSoftware.pm:$$: Project is public, no restriction here\n"; - $r->set_handlers(PerlAuthenHandler => [\&OK]) - } else { # private - print STDERR "SoundSoftware.pm:$$: Project is private, authentication handler required\n"; + if ($status == 1) { # public + + print STDERR "SoundSoftware.pm:$$: Project is public\n"; + + if (!defined $read_only_methods{$method}) { + + print STDERR "SoundSoftware.pm:$$: Method is not read-only\n"; + + if ($readonly) { + print STDERR "SoundSoftware.pm:$$: Project repo is read-only, refusing access\n"; + return FORBIDDEN; + } else { + print STDERR "SoundSoftware.pm:$$: Project repo is read-write, auth required\n"; + # fall through, this is the normal case + } + + } else { + # Public project, read-only method -- this is the only + # case we can decide for certain to accept in this function + print STDERR "SoundSoftware.pm:$$: Method is read-only, no restriction here\n"; + $r->set_handlers(PerlAuthenHandler => [\&OK]); + return OK; + } + + } else { # status != 1, i.e. nonexistent or private -- equivalent here + + print STDERR "SoundSoftware.pm:$$: Project is private or nonexistent, auth required\n"; + # fall through } - return OK + if ($cfg->{SoundSoftwareSslRequired} eq "on") { + if ($r->dir_config('HTTPS') eq "on") { + return OK; + } else { + my $redir_to = "https://" . $r->hostname() . $r->unparsed_uri(); + print STDERR "SoundSoftware.pm:$$: Need to switch to HTTPS, redirecting to $redir_to\n"; + $r->header_out(Location => $redir_to); + return REDIRECT; + } + } else if ($cfg->{SoundSoftwareSslRequired} eq "off") { + return OK; + } else { + print STDERR "WARNING: SoundSoftware.pm:$$: SoundSoftwareSslRequired should be either 'on' or 'off'\n"; + return OK; + } } sub authen_handler { @@ -237,6 +286,16 @@ print STDERR "SoundSoftware.pm:$$: User is " . $r->user . ", got password\n"; + my $status = get_project_status($dbh, $project_id, $r); + if ($status == 0) { + # nonexistent, behave like private project you aren't a member of + print STDERR "SoundSoftware.pm:$$: Project doesn't exist, not permitted\n"; + $dbh->disconnect(); + undef $dbh; + $r->note_auth_failure(); + return AUTH_REQUIRED; + } + my $permitted = is_permitted($dbh, $project_id, $r->user, $redmine_pass, $r); $dbh->disconnect();