Mercurial > hg > soundsoftware-site
comparison 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 |
comparison
equal
deleted
inserted
replaced
519:3be6bc3c2a17 | 524:1248a47e81b3 |
---|---|
22 3. Push to repo for public project: "Permitted" users only (this | 22 3. Push to repo for public project: "Permitted" users only (this |
23 probably means project members who are also identified in the hgrc web | 23 probably means project members who are also identified in the hgrc web |
24 section for the repository and so will be approved by hgwebdir?) | 24 section for the repository and so will be approved by hgwebdir?) |
25 | 25 |
26 4. Push to repo for private project: "Permitted" users only (as above) | 26 4. Push to repo for private project: "Permitted" users only (as above) |
27 | |
28 5. Push to any repo that is tracking an external repo: Refused always | |
27 | 29 |
28 =head1 INSTALLATION | 30 =head1 INSTALLATION |
29 | 31 |
30 Debian/ubuntu: | 32 Debian/ubuntu: |
31 | 33 |
112 | 114 |
113 sub SoundSoftwareDSN { | 115 sub SoundSoftwareDSN { |
114 my ($self, $parms, $arg) = @_; | 116 my ($self, $parms, $arg) = @_; |
115 $self->{SoundSoftwareDSN} = $arg; | 117 $self->{SoundSoftwareDSN} = $arg; |
116 my $query = "SELECT | 118 my $query = "SELECT |
117 hashed_password, auth_source_id, permissions | 119 hashed_password, salt, auth_source_id, permissions |
118 FROM members, projects, users, roles, member_roles | 120 FROM members, projects, users, roles, member_roles |
119 WHERE | 121 WHERE |
120 projects.id=members.project_id | 122 projects.id=members.project_id |
121 AND member_roles.member_id=members.id | 123 AND member_roles.member_id=members.id |
122 AND users.id=members.user_id | 124 AND users.id=members.user_id |
158 my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/; | 160 my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/; |
159 | 161 |
160 sub access_handler { | 162 sub access_handler { |
161 my $r = shift; | 163 my $r = shift; |
162 | 164 |
163 print STDERR "SoundSoftware.pm: In access handler at " . scalar localtime() . "\n"; | 165 print STDERR "SoundSoftware.pm:$$: In access handler at " . scalar localtime() . "\n"; |
164 | 166 |
165 unless ($r->some_auth_required) { | 167 unless ($r->some_auth_required) { |
166 $r->log_reason("No authentication has been configured"); | 168 $r->log_reason("No authentication has been configured"); |
167 return FORBIDDEN; | 169 return FORBIDDEN; |
168 } | 170 } |
169 | 171 |
170 my $method = $r->method; | 172 my $method = $r->method; |
171 | 173 |
172 print STDERR "SoundSoftware.pm: Method: $method, uri " . $r->uri . ", location " . $r->location . "\n"; | 174 print STDERR "SoundSoftware.pm:$$: Method: $method, uri " . $r->uri . ", location " . $r->location . "\n"; |
173 print STDERR "SoundSoftware.pm: Accept: " . $r->headers_in->{Accept} . "\n"; | 175 print STDERR "SoundSoftware.pm:$$: Accept: " . $r->headers_in->{Accept} . "\n"; |
174 | |
175 if (!defined $read_only_methods{$method}) { | |
176 print STDERR "SoundSoftware.pm: Method is not read-only, authentication handler required\n"; | |
177 return OK; | |
178 } | |
179 | 176 |
180 my $dbh = connect_database($r); | 177 my $dbh = connect_database($r); |
181 unless ($dbh) { | 178 unless ($dbh) { |
182 print STDERR "SoundSoftware.pm: Database connection failed!: " . $DBI::errstr . "\n"; | 179 print STDERR "SoundSoftware.pm:$$: Database connection failed!: " . $DBI::errstr . "\n"; |
183 return FORBIDDEN; | 180 return FORBIDDEN; |
184 } | 181 } |
185 | 182 |
186 | 183 print STDERR "Connected to db, dbh is " . $dbh . "\n"; |
187 print STDERR "Connected to db, dbh is " . $dbh . "\n"; | |
188 | 184 |
189 my $project_id = get_project_identifier($dbh, $r); | 185 my $project_id = get_project_identifier($dbh, $r); |
186 | |
187 if (!defined $read_only_methods{$method}) { | |
188 print STDERR "SoundSoftware.pm:$$: Method is not read-only\n"; | |
189 if (project_repo_is_readonly($dbh, $project_id, $r)) { | |
190 print STDERR "SoundSoftware.pm:$$: Project repo is read-only, refusing access\n"; | |
191 return FORBIDDEN; | |
192 } else { | |
193 print STDERR "SoundSoftware.pm:$$: Project repo is read-write, authentication handler required\n"; | |
194 return OK; | |
195 } | |
196 } | |
197 | |
190 my $status = get_project_status($dbh, $project_id, $r); | 198 my $status = get_project_status($dbh, $project_id, $r); |
191 | 199 |
192 $dbh->disconnect(); | 200 $dbh->disconnect(); |
193 undef $dbh; | 201 undef $dbh; |
194 | 202 |
195 if ($status == 0) { # nonexistent | 203 if ($status == 0) { # nonexistent |
196 print STDERR "SoundSoftware.pm: Project does not exist, refusing access\n"; | 204 print STDERR "SoundSoftware.pm:$$: Project does not exist, refusing access\n"; |
197 return FORBIDDEN; | 205 return FORBIDDEN; |
198 } elsif ($status == 1) { # public | 206 } elsif ($status == 1) { # public |
199 print STDERR "SoundSoftware.pm: Project is public, no restriction here\n"; | 207 print STDERR "SoundSoftware.pm:$$: Project is public, no restriction here\n"; |
200 $r->set_handlers(PerlAuthenHandler => [\&OK]) | 208 $r->set_handlers(PerlAuthenHandler => [\&OK]) |
201 } else { # private | 209 } else { # private |
202 print STDERR "SoundSoftware.pm: Project is private, authentication handler required\n"; | 210 print STDERR "SoundSoftware.pm:$$: Project is private, authentication handler required\n"; |
203 } | 211 } |
204 | 212 |
205 return OK | 213 return OK |
206 } | 214 } |
207 | 215 |
208 sub authen_handler { | 216 sub authen_handler { |
209 my $r = shift; | 217 my $r = shift; |
210 | 218 |
211 print STDERR "SoundSoftware.pm: In authentication handler at " . scalar localtime() . "\n"; | 219 print STDERR "SoundSoftware.pm:$$: In authentication handler at " . scalar localtime() . "\n"; |
212 | 220 |
213 my $dbh = connect_database($r); | 221 my $dbh = connect_database($r); |
214 unless ($dbh) { | 222 unless ($dbh) { |
215 print STDERR "SoundSoftware.pm: Database connection failed!: " . $DBI::errstr . "\n"; | 223 print STDERR "SoundSoftware.pm:$$: Database connection failed!: " . $DBI::errstr . "\n"; |
216 return AUTH_REQUIRED; | 224 return AUTH_REQUIRED; |
217 } | 225 } |
218 | 226 |
219 my $project_id = get_project_identifier($dbh, $r); | 227 my $project_id = get_project_identifier($dbh, $r); |
220 my $realm = get_realm($dbh, $project_id, $r); | 228 my $realm = get_realm($dbh, $project_id, $r); |
225 $dbh->disconnect(); | 233 $dbh->disconnect(); |
226 undef $dbh; | 234 undef $dbh; |
227 return $res; | 235 return $res; |
228 } | 236 } |
229 | 237 |
230 print STDERR "SoundSoftware.pm: User is " . $r->user . ", got password\n"; | 238 print STDERR "SoundSoftware.pm:$$: User is " . $r->user . ", got password\n"; |
231 | 239 |
232 my $permitted = is_permitted($dbh, $project_id, $r->user, $redmine_pass, $r); | 240 my $permitted = is_permitted($dbh, $project_id, $r->user, $redmine_pass, $r); |
233 | 241 |
234 $dbh->disconnect(); | 242 $dbh->disconnect(); |
235 undef $dbh; | 243 undef $dbh; |
236 | 244 |
237 if ($permitted) { | 245 if ($permitted) { |
238 return OK; | 246 return OK; |
239 } else { | 247 } else { |
240 print STDERR "SoundSoftware.pm: Not permitted\n"; | 248 print STDERR "SoundSoftware.pm:$$: Not permitted\n"; |
241 $r->note_auth_failure(); | 249 $r->note_auth_failure(); |
242 return AUTH_REQUIRED; | 250 return AUTH_REQUIRED; |
243 } | 251 } |
244 } | 252 } |
245 | 253 |
269 undef $sth; | 277 undef $sth; |
270 | 278 |
271 $ret; | 279 $ret; |
272 } | 280 } |
273 | 281 |
282 sub project_repo_is_readonly { | |
283 my $dbh = shift; | |
284 my $project_id = shift; | |
285 my $r = shift; | |
286 | |
287 if (!defined $project_id or $project_id eq '') { | |
288 return 0; # nonexistent | |
289 } | |
290 | |
291 my $sth = $dbh->prepare( | |
292 "SELECT repositories.is_external FROM repositories, projects WHERE projects.identifier = ? AND repositories.project_id = projects.id;" | |
293 ); | |
294 | |
295 $sth->execute($project_id); | |
296 my $ret = 0; # nonexistent | |
297 if (my @row = $sth->fetchrow_array) { | |
298 if (defined($row[0]) && ($row[0] eq "1" || $row[0] eq "t")) { | |
299 $ret = 1; # read-only (i.e. external) | |
300 } else { | |
301 $ret = 0; # read-write | |
302 } | |
303 } | |
304 $sth->finish(); | |
305 undef $sth; | |
306 | |
307 $ret; | |
308 } | |
309 | |
274 sub is_permitted { | 310 sub is_permitted { |
275 my $dbh = shift; | 311 my $dbh = shift; |
276 my $project_id = shift; | 312 my $project_id = shift; |
277 my $redmine_user = shift; | 313 my $redmine_user = shift; |
278 my $redmine_pass = shift; | 314 my $redmine_pass = shift; |
286 my $query = $cfg->{SoundSoftwareQuery}; | 322 my $query = $cfg->{SoundSoftwareQuery}; |
287 my $sth = $dbh->prepare($query); | 323 my $sth = $dbh->prepare($query); |
288 $sth->execute($redmine_user, $project_id); | 324 $sth->execute($redmine_user, $project_id); |
289 | 325 |
290 my $ret; | 326 my $ret; |
291 while (my ($hashed_password, $auth_source_id, $permissions) = $sth->fetchrow_array) { | 327 while (my ($hashed_password, $salt, $auth_source_id, $permissions) = $sth->fetchrow_array) { |
292 | 328 |
293 # Test permissions for this user before we verify credentials | 329 # Test permissions for this user before we verify credentials |
294 # -- if the user is not permitted this action anyway, there's | 330 # -- if the user is not permitted this action anyway, there's |
295 # not much point in e.g. contacting the LDAP | 331 # not much point in e.g. contacting the LDAP |
296 | 332 |
303 # credentials checked out -- test those now | 339 # credentials checked out -- test those now |
304 | 340 |
305 print STDERR "SoundSoftware.pm: User $redmine_user has required role, checking credentials\n"; | 341 print STDERR "SoundSoftware.pm: User $redmine_user has required role, checking credentials\n"; |
306 | 342 |
307 unless ($auth_source_id) { | 343 unless ($auth_source_id) { |
308 if ($hashed_password eq $pass_digest) { | 344 my $salted_password = Digest::SHA1::sha1_hex($salt.$pass_digest); |
345 if ($hashed_password eq $salted_password) { | |
309 print STDERR "SoundSoftware.pm: User $redmine_user authenticated via password\n"; | 346 print STDERR "SoundSoftware.pm: User $redmine_user authenticated via password\n"; |
310 $ret = 1; | 347 $ret = 1; |
311 last; | 348 last; |
312 } | 349 } |
313 } else { | 350 } else { |
323 binddn => $rowldap[3] ? $rowldap[3] : "", | 360 binddn => $rowldap[3] ? $rowldap[3] : "", |
324 bindpw => $rowldap[4] ? $rowldap[4] : "", | 361 bindpw => $rowldap[4] ? $rowldap[4] : "", |
325 filter => "(".$rowldap[6]."=%s)" | 362 filter => "(".$rowldap[6]."=%s)" |
326 ); | 363 ); |
327 if ($ldap->authenticate($redmine_user, $redmine_pass)) { | 364 if ($ldap->authenticate($redmine_user, $redmine_pass)) { |
328 print STDERR "SoundSoftware.pm: User $redmine_user authenticated via LDAP\n"; | 365 print STDERR "SoundSoftware.pm:$$: User $redmine_user authenticated via LDAP\n"; |
329 $ret = 1; | 366 $ret = 1; |
330 } | 367 } |
331 } | 368 } |
332 $sthldap->finish(); | 369 $sthldap->finish(); |
333 undef $sthldap; | 370 undef $sthldap; |
334 } | 371 } |
335 } else { | 372 } else { |
336 print STDERR "SoundSoftware.pm: User $redmine_user lacks required role for this project\n"; | 373 print STDERR "SoundSoftware.pm:$$: User $redmine_user lacks required role for this project\n"; |
337 } | 374 } |
338 } | 375 } |
339 | 376 |
340 $sth->finish(); | 377 $sth->finish(); |
341 undef $sth; | 378 undef $sth; |
382 $identifier = $row[0]; | 419 $identifier = $row[0]; |
383 } | 420 } |
384 $sth->finish(); | 421 $sth->finish(); |
385 undef $sth; | 422 undef $sth; |
386 | 423 |
387 print STDERR "SoundSoftware.pm: Repository '$repo' belongs to project '$identifier'\n"; | 424 print STDERR "SoundSoftware.pm:$$: Repository '$repo' belongs to project '$identifier'\n"; |
388 | 425 |
389 $identifier; | 426 $identifier; |
390 } | 427 } |
391 | 428 |
392 sub get_realm { | 429 sub get_realm { |