diff extra/soundsoftware/SoundSoftware.pm @ 524:1248a47e81b3 feature_36

Merge from branch "luisf"
author luisf <luis.figueira@eecs.qmul.ac.uk>
date Mon, 25 Jul 2011 14:39:38 +0100
parents a2192366d309
children 897bc2b63bfe
line wrap: on
line diff
--- a/extra/soundsoftware/SoundSoftware.pm	Fri Jul 15 17:21:05 2011 +0100
+++ b/extra/soundsoftware/SoundSoftware.pm	Mon Jul 25 14:39:38 2011 +0100
@@ -25,6 +25,8 @@
 
 4. Push to repo for private project: "Permitted" users only (as above)
 
+5. Push to any repo that is tracking an external repo: Refused always
+
 =head1 INSTALLATION
 
 Debian/ubuntu:
@@ -114,7 +116,7 @@
     my ($self, $parms, $arg) = @_;
     $self->{SoundSoftwareDSN} = $arg;
     my $query = "SELECT 
-                 hashed_password, auth_source_id, permissions
+                 hashed_password, salt, auth_source_id, permissions
               FROM members, projects, users, roles, member_roles
               WHERE 
                 projects.id=members.project_id
@@ -160,7 +162,7 @@
 sub access_handler {
     my $r = shift;
 
-    print STDERR "SoundSoftware.pm: In access handler at " . scalar localtime() . "\n";
+    print STDERR "SoundSoftware.pm:$$: In access handler at " . scalar localtime() . "\n";
 
     unless ($r->some_auth_required) {
 	$r->log_reason("No authentication has been configured");
@@ -169,37 +171,43 @@
 
     my $method = $r->method;
 
-    print STDERR "SoundSoftware.pm: Method: $method, uri " . $r->uri . ", location " . $r->location . "\n";
-    print STDERR "SoundSoftware.pm: Accept: " . $r->headers_in->{Accept} . "\n";
-
-    if (!defined $read_only_methods{$method}) {
-	print STDERR "SoundSoftware.pm: Method is not read-only, authentication handler required\n";
-	return OK;
-    }
+    print STDERR "SoundSoftware.pm:$$: Method: $method, uri " . $r->uri . ", location " . $r->location . "\n";
+    print STDERR "SoundSoftware.pm:$$: Accept: " . $r->headers_in->{Accept} . "\n";
 
     my $dbh = connect_database($r);
     unless ($dbh) {
-	print STDERR "SoundSoftware.pm: Database connection failed!: " . $DBI::errstr . "\n";
+	print STDERR "SoundSoftware.pm:$$: Database connection failed!: " . $DBI::errstr . "\n";
 	return FORBIDDEN;
     }
 
-
-print STDERR "Connected to db, dbh is " . $dbh . "\n";
+    print STDERR "Connected to db, dbh is " . $dbh . "\n";
 
     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;
+        }
+    }
+
     my $status = get_project_status($dbh, $project_id, $r);
 
     $dbh->disconnect();
     undef $dbh;
 
     if ($status == 0) { # nonexistent
-	print STDERR "SoundSoftware.pm: Project does not exist, refusing access\n";
+	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";
+	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";
+	print STDERR "SoundSoftware.pm:$$: Project is private, authentication handler required\n";
     }
 
     return OK
@@ -208,11 +216,11 @@
 sub authen_handler {
     my $r = shift;
     
-    print STDERR "SoundSoftware.pm: In authentication handler at " . scalar localtime() . "\n";
+    print STDERR "SoundSoftware.pm:$$: In authentication handler at " . scalar localtime() . "\n";
 
     my $dbh = connect_database($r);
     unless ($dbh) {
-        print STDERR "SoundSoftware.pm: Database connection failed!: " . $DBI::errstr . "\n";
+        print STDERR "SoundSoftware.pm:$$: Database connection failed!: " . $DBI::errstr . "\n";
         return AUTH_REQUIRED;
     }
     
@@ -227,7 +235,7 @@
 	return $res;
     }
     
-    print STDERR "SoundSoftware.pm: User is " . $r->user . ", got password\n";
+    print STDERR "SoundSoftware.pm:$$: User is " . $r->user . ", got password\n";
 
     my $permitted = is_permitted($dbh, $project_id, $r->user, $redmine_pass, $r);
     
@@ -237,7 +245,7 @@
     if ($permitted) {
 	return OK;
     } else {
-	print STDERR "SoundSoftware.pm: Not permitted\n";
+	print STDERR "SoundSoftware.pm:$$: Not permitted\n";
 	$r->note_auth_failure();
 	return AUTH_REQUIRED;
     }
@@ -271,6 +279,34 @@
     $ret;
 }
 
+sub project_repo_is_readonly {
+    my $dbh = shift;
+    my $project_id = shift;
+    my $r = shift;
+
+    if (!defined $project_id or $project_id eq '') {
+        return 0; # nonexistent
+    }
+
+    my $sth = $dbh->prepare(
+        "SELECT repositories.is_external FROM repositories, projects WHERE projects.identifier = ? AND repositories.project_id = projects.id;"
+    );
+
+    $sth->execute($project_id);
+    my $ret = 0; # nonexistent
+    if (my @row = $sth->fetchrow_array) {
+        if (defined($row[0]) && ($row[0] eq "1" || $row[0] eq "t")) {
+            $ret = 1; # read-only (i.e. external)
+        } else {
+            $ret = 0; # read-write
+        }
+    }
+    $sth->finish();
+    undef $sth;
+
+    $ret;
+}
+
 sub is_permitted {
     my $dbh = shift;
     my $project_id = shift;
@@ -288,7 +324,7 @@
     $sth->execute($redmine_user, $project_id);
 
     my $ret;
-    while (my ($hashed_password, $auth_source_id, $permissions) = $sth->fetchrow_array) {
+    while (my ($hashed_password, $salt, $auth_source_id, $permissions) = $sth->fetchrow_array) {
 
 	# Test permissions for this user before we verify credentials
 	# -- if the user is not permitted this action anyway, there's
@@ -305,7 +341,8 @@
 	    print STDERR "SoundSoftware.pm: User $redmine_user has required role, checking credentials\n";
 
 	    unless ($auth_source_id) {
-		if ($hashed_password eq $pass_digest) {
+                my $salted_password = Digest::SHA1::sha1_hex($salt.$pass_digest);
+		if ($hashed_password eq $salted_password) {
 		    print STDERR "SoundSoftware.pm: User $redmine_user authenticated via password\n";
 		    $ret = 1;
 		    last;
@@ -325,7 +362,7 @@
 			filter  => "(".$rowldap[6]."=%s)"
 			);
 		    if ($ldap->authenticate($redmine_user, $redmine_pass)) {
-			print STDERR "SoundSoftware.pm: User $redmine_user authenticated via LDAP\n";
+			print STDERR "SoundSoftware.pm:$$: User $redmine_user authenticated via LDAP\n";
 			$ret = 1;
 		    }
 		}
@@ -333,7 +370,7 @@
 		undef $sthldap;
 	    }
 	} else {
-	    print STDERR "SoundSoftware.pm: User $redmine_user lacks required role for this project\n";
+	    print STDERR "SoundSoftware.pm:$$: User $redmine_user lacks required role for this project\n";
 	}
     }
 
@@ -384,7 +421,7 @@
     $sth->finish();
     undef $sth;
 
-    print STDERR "SoundSoftware.pm: Repository '$repo' belongs to project '$identifier'\n";
+    print STDERR "SoundSoftware.pm:$$: Repository '$repo' belongs to project '$identifier'\n";
 
     $identifier;
 }