Compare commits

...

20 Commits

Author SHA1 Message Date
Liwiusz Ociepa
131b15fc7a Fix access to Repository Parent Path (FORBIDEN instead of AUTH_REQUIRED).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/swistak@2058 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-11-27 14:51:14 +00:00
Liwiusz Ociepa
f6b1583a1a If project_id is uninitialized, initialize it.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/swistak@2050 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-11-20 13:46:06 +00:00
Liwiusz Ociepa
5bea900443 Some debug added.
There is a bug - don't know if in Redmine.pm or in Netbeans svn client.
In logs:
Use of uninitialized value $project_id in concatenation (.) or string at 
/usr/lib/perl5/Apache/Authn/Redmine.pm line 306, ....


git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/swistak@2049 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-11-20 11:21:14 +00:00
Liwiusz Ociepa
81baddad00 - Disable debug,
- Fix namespace set condition (setting namespace, without 
  configured memcached, should segfault apache before).


git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1646 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-07-08 15:06:41 +00:00
Liwiusz Ociepa
f6b5632fec Remove default Memcached namespace.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1645 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-07-07 21:34:43 +00:00
Liwiusz Ociepa
f7ede727fd Initial support for caching credentials in Memcached (debug is enabled).
Support for caching in Apache memory pools has been dropped.


git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1644 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-07-07 17:26:39 +00:00
Liwiusz Ociepa
b870417860 Merge changes from trunk.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1618 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-07-04 13:25:32 +00:00
Liwiusz Ociepa
25a7838e0a Memory leak (postgres -> zlib + ssl) has been fixed by apache developers.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1438 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-19 12:41:40 +00:00
Liwiusz Ociepa
7c3ddf2bc0 Simple change to allow multiple RedmineDbWhereClause and added errmsg for RedmineCacheCredsMax
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1424 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-13 09:06:11 +00:00
Liwiusz Ociepa
0f8df81b87 Do not crash on reload.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1423 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-08 22:06:44 +00:00
Liwiusz Ociepa
c5121d804d Fix when you don't define RedmineDbWhereClause
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1422 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-08 17:10:25 +00:00
Liwiusz Ociepa
8bcbbebf65 Small fix for not read-only methods.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1421 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-07 09:22:50 +00:00
Liwiusz Ociepa
2d2afab549 Fix comment about configuration.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1420 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-06 19:51:34 +00:00
Liwiusz Ociepa
35f601e769 Cache Credentials added (login:proj -> "sha1_hex(pass))
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1419 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-06 15:14:58 +00:00
Liwiusz Ociepa
b84cffd62e Strip extra whitespaces from query in apache config object.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1418 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-05 15:00:50 +00:00
Liwiusz Ociepa
2eba0b66d4 Comment to memory leak with Postgres and ssl.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1417 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-05 13:35:56 +00:00
Liwiusz Ociepa
eb2d814344 http://perl.apache.org/docs/2.0/user/config/custom.html#Description
Rewrite module not to use PerlSetVar


git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1416 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-05-05 13:18:41 +00:00
Liwiusz Ociepa
d9385ce9a2 Add support for db_where_clause - that variable is appended to password query.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1378 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-04-28 17:49:49 +00:00
Liwiusz Ociepa
d3522c10e4 Sync Redmine.pm with trunk.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1377 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-04-28 17:44:00 +00:00
Jean-Philippe Lang
b9957264eb swistak branch added.
git-svn-id: http://redmine.rubyforge.org/svn/branches/swistak@1313 e93f8b46-1217-0410-a6f0-8f06a7374b81
2008-03-31 17:01:50 +00:00

View File

@@ -8,8 +8,8 @@ against redmine database
=head1 SYNOPSIS
This module allow anonymous users to browse public project and
registred users to browse and commit their project. authentication is
done on the redmine database.
registred users to browse and commit their project. Authentication is
done against the redmine database or the LDAP configured in redmine.
This method is far simpler than the one with pam_* and works with all
database without an hassle but you need to have apache/mod_perl on the
@@ -29,12 +29,16 @@ On debian/ubuntu you must do :
aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
If your Redmine users use LDAP authentication, you will also need
Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used):
aptitude install libauthen-simple-ldap-perl libio-socket-ssl-perl
=head1 CONFIGURATION
## if the module isn't in your perl path
PerlRequire /usr/local/apache/Redmine.pm
## else
# PerlModule Apache::Authn::Redmine
## This module has to be in your perl path
## eg: /usr/lib/perl5/Apache/Authn/Redmine.pm
PerlLoadModule Apache::Authn::Redmine
<Location /svn>
DAV svn
SVNParentPath "/var/svn"
@@ -47,12 +51,19 @@ On debian/ubuntu you must do :
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
## for mysql
PerlSetVar dsn DBI:mysql:database=databasename;host=my.db.server
RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"
## for postgres
# PerlSetVar dsn DBI:Pg:dbname=databasename;host=my.db.server
# RedmineDSN "DBI:Pg:dbname=databasename;host=my.db.server"
PerlSetVar db_user redmine
PerlSetVar db_pass password
RedmineDbUser "redmine"
RedmineDbPass "password"
## Optional where clause (fulltext search would be slow and
## database dependant).
# RedmineDbWhereClause "and members.role_id IN (1,2)"
## Configuration for memcached
# RedmineMemcacheServers "127.0.0.1:112211"
# RedmineMemcacheExpirySec "60"
# RedmineMemcacheNamespace "RedmineCreds:"
</Location>
To be able to browse repository inside redmine, you must add something
@@ -87,18 +98,119 @@ And you need to upgrade at least reposman.rb (after r860).
=cut
use strict;
use warnings FATAL => 'all', NONFATAL => 'redefine';
use DBI;
use Digest::SHA1;
# optional module for LDAP authentication
my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
my $CanUseMemcached = eval("use Cache::Memcached; 1");
use Apache2::Module;
use Apache2::Access;
use Apache2::ServerRec qw();
use Apache2::RequestRec qw();
use Apache2::RequestUtil qw();
use Apache2::Const qw(:common);
use Apache2::Const qw(:common :override :cmd_how);
# use Apache2::Directive qw();
my @directives = (
{
name => 'RedmineDSN',
req_override => OR_AUTHCFG,
args_how => TAKE1,
errmsg => 'Dsn in format used by Perl DBI. eg: "DBI:Pg:dbname=databasename;host=my.db.server"',
},
{
name => 'RedmineDbUser',
req_override => OR_AUTHCFG,
args_how => TAKE1,
},
{
name => 'RedmineDbPass',
req_override => OR_AUTHCFG,
args_how => TAKE1,
},
{
name => 'RedmineDbWhereClause',
req_override => OR_AUTHCFG,
args_how => TAKE1,
},
{
name => 'RedmineMemcacheServers',
req_override => OR_AUTHCFG,
args_how => TAKE1,
},
{
name => 'RedmineMemcacheExpirySec',
req_override => OR_AUTHCFG,
args_how => TAKE1,
},
{
name => 'RedmineMemcacheNamespace',
req_override => OR_AUTHCFG,
args_how => TAKE1,
},
);
sub RedmineDSN {
my ($self, $parms, $arg) = @_;
$self->{RedmineDSN} = $arg;
my $query = "SELECT
hashed_password, auth_source_id
FROM members, projects, users
WHERE
projects.id=members.project_id
AND users.id=members.user_id
AND users.status=1
AND login=?
AND identifier=? ";
$self->{RedmineQuery} = trim($query);
}
sub RedmineDbUser { set_val('RedmineDbUser', @_); }
sub RedmineDbPass { set_val('RedmineDbPass', @_); }
sub RedmineDbWhereClause {
my ($self, $parms, $arg) = @_;
$self->{RedmineQuery} = trim($self->{RedmineQuery}.($arg ? $arg : "")." ");
}
sub RedmineMemcacheServers {
my ($self, $parms, $arg) = @_;
if ($arg && $CanUseMemcached) {
$self->{RedmineMemcached} = new Cache::Memcached {
'servers' => [ $arg, ],
'debug' => 0,
};
$self->{RedmineMemcache} = 1;
}
}
sub RedmineMemcacheExpirySec { set_val('RedmineMemcacheExpirySec', @_); }
sub RedmineMemcacheNamespace {
my ($self, $parms, $arg) = @_;
if ($self->{RedmineMemcache}) {
# Undocumented feature of Cache::Memcached, please don't kill me
$self->{RedmineMemcached}->{namespace} = $arg;
$self->{RedmineMemcached}->{namespace_len} = length $self->{RedmineMemcached}->{namespace};
}
}
sub trim {
my $string = shift;
$string =~ s/\s{2,}/ /g;
return $string;
}
sub set_val {
my ($key, $self, $parms, $arg) = @_;
$self->{$key} = $arg;
}
Apache2::Module::add(__PACKAGE__, \@directives);
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
sub access_handler {
@@ -110,7 +222,7 @@ sub access_handler {
}
my $method = $r->method;
return OK unless 1 == $read_only_methods{$method};
return OK if defined $read_only_methods{$method};
my $project_id = get_project_identifier($r);
@@ -126,7 +238,11 @@ sub authen_handler {
my ($res, $redmine_pass) = $r->get_basic_auth_pw();
return $res unless $res == OK;
if (is_member($r->user, $redmine_pass, $r)) {
my $project_id = get_project_identifier($r);
if (!$project_id) {
return FORBIDDEN;
}
if (is_member($r->user, $redmine_pass, $r, $project_id)) {
return OK;
} else {
$r->note_auth_failure();
@@ -138,6 +254,10 @@ sub is_public_project {
my $project_id = shift;
my $r = shift;
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
if ($cfg->{RedmineMemcache}) {
return 1 if ($cfg->{RedmineMemcached}->get($project_id));
}
my $dbh = connect_database($r);
my $sth = $dbh->prepare(
"SELECT * FROM projects WHERE projects.identifier=? and projects.is_public=true;"
@@ -145,7 +265,16 @@ sub is_public_project {
$sth->execute($project_id);
my $ret = $sth->fetchrow_array ? 1 : 0;
$sth->finish();
$dbh->disconnect();
if ($cfg->{RedmineMemcache}) {
if ($cfg->{RedmineMemcacheExpirySec}) {
$cfg->{RedmineMemcached}->set($project_id, $ret, $cfg->{RedmineMemcacheExpirySec});
} else {
$cfg->{RedmineMemcached}->set($project_id, $ret);
}
}
$ret;
}
@@ -169,26 +298,59 @@ sub is_member {
my $redmine_user = shift;
my $redmine_pass = shift;
my $r = shift;
my $project_id = shift;
my $dbh = connect_database($r);
my $project_id = get_project_identifier($r);
my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
my $sth = $dbh->prepare(
"SELECT hashed_password FROM members, projects, users WHERE projects.id=members.project_id AND users.id=members.user_id AND users.status=1 AND login=? AND identifier=?;"
);
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
my $usrprojpass;
if ($cfg->{RedmineMemcache}) {
$usrprojpass = $cfg->{RedmineMemcached}->get($redmine_user.":".$project_id);
return 1 if (defined $usrprojpass and ($usrprojpass eq $pass_digest));
}
my $query = $cfg->{RedmineQuery};
my $sth = $dbh->prepare($query);
$sth->execute($redmine_user, $project_id);
my $ret;
while (my @row = $sth->fetchrow_array) {
unless ($row[1]) {
if ($row[0] eq $pass_digest) {
$ret = 1;
last;
}
} elsif ($CanUseLDAPAuth) {
my $sthldap = $dbh->prepare(
"SELECT host,port,tls,account,account_password,base_dn,attr_login from auth_sources WHERE id = ?;"
);
$sthldap->execute($row[1]);
while (my @rowldap = $sthldap->fetchrow_array) {
my $ldap = Authen::Simple::LDAP->new(
host => ($rowldap[2] == 1 || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0],
port => $rowldap[1],
basedn => $rowldap[5],
binddn => $rowldap[3] ? $rowldap[3] : "",
bindpw => $rowldap[4] ? $rowldap[4] : "",
filter => "(".$rowldap[6]."=%s)"
);
$ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass));
}
$sthldap->finish();
}
}
$sth->finish();
$dbh->disconnect();
if ($cfg->{RedmineMemcache} and $ret) {
if ($cfg->{RedmineMemcacheExpirySec}) {
$cfg->{RedmineMemcached}->set($redmine_user.":".$project_id, $pass_digest, $cfg->{RedmineMemcacheExpirySec});
} else {
$cfg->{RedmineMemcached}->set($redmine_user.":".$project_id, $pass_digest);
}
}
$ret;
}
@@ -203,8 +365,8 @@ sub get_project_identifier {
sub connect_database {
my $r = shift;
my ($dsn, $db_user, $db_pass) = map { $r->dir_config($_) } qw/dsn db_user db_pass/;
return DBI->connect($dsn, $db_user, $db_pass);
my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
return DBI->connect($cfg->{RedmineDSN}, $cfg->{RedmineDbUser}, $cfg->{RedmineDbPass});
}
1;