Authentication SVN with Redmine fails

Added by Philippe Camps 5 months ago

My environment :
Cents OS 7.5 with redmine 3.4.6, postgresql10-10.6-1, svn 1.7.14

I have installed redmine following the howto https://www.redmine.org/projects/redmine/wiki/Install_Redmine_346_on_Centos_75
Redmine works fine et I can authenticate with local account in database and with ldap account.

But when I want to authenticate SVN with Redmine, it is not working with Redmine.pm
I can see with postgres logs that Redmine.pm do requests to redmine database :

2018-11-27 17:12:25.077 CET [24956] LOG: exécute dbdpg_p24246_1: SELECT is_public FROM projects
WHERE projects.identifier = $1 AND projects.status <> 9
AND EXISTS (SELECT 1 FROM enabled_modules em WHERE em.project_id = projects.id AND em.name = 'repository');

This corresponds to Redmine.pm code :

@sub is_public_project {
my $project_id = shift;
my $r = shift;

if (is_authentication_forced($r)) {
return 0;
}
my $dbh = connect_database($r);
my $sth = $dbh->prepare(
"SELECT is_public FROM projects
WHERE projects.identifier = ? AND projects.status <> 9
AND EXISTS (SELECT 1 FROM enabled_modules em WHERE em.project_id = projects.id AND em.name = 'repository');"
);@

Next logs :

2018-11-27 17:12:25.093 CET [24957] LOG: exécute dbdpg_p24246_1: SELECT users.hashed_password, users.salt, users.auth_source_id, roles.permissions, projects.status FROM projects, users, roles WHERE users.login=$1 AND projects.identifier=$2 AND EXISTS (SELECT 1 FROM enabled_modules em WHERE em.project_id = projects.id AND em.name = 'repository') AND users.type='User' AND users.status=1 AND ( roles.id IN (SELECT member_roles.role_id FROM members, member_roles WHERE members.user_id = users.id AND members.project_id = projects.id AND members.id = member_roles.member_id) OR (cast(projects.is_public as CHAR) IN ('t', '1') AND (roles.builtin=1 OR roles.id IN (SELECT member_roles.role_id FROM members, member_roles, users g WHERE members.user_id = g.id AND members.project_id = projects.id AND members.id = member_roles.member_id AND g.type = 'GroupNonMember')) ) ) AND roles.permissions IS NOT NULL
2018-11-27 17:12:25.093 CET [24957] DÉTAIL: paramètres : $1 = 'camps', $2 = 'repo-projet-test1'

So, my httpd config is good because perl module is used to connect to postgres :
@
PerlLoadModule Apache::Authn::Redmine
PerlModule DBI
PerlOptions +GlobalRequest

PerlLoadModule Authen::Simple::LDAP
PerlLoadModule IO::Socket::SSL
&lt;Location /svn&gt;
DAV svn
SVNParentPath "/var/www/svn"
SVNReposName "IES SVN Repository"
LimitXMLRequestBody 0
SVNPathAuthz off
PerlAccessHandler Apache::Authn::Redmine::access_handler
PerlAuthenHandler Apache::Authn::Redmine::authen_handler
AuthType Basic
AuthName "Redmine SVN Auth"
AuthUserFile /dev/null
&lt;Limit GET PROPFIND REPORT&gt;
&lt;RequireAny&gt;
Require valid-user
Require local
#Require all granted
&lt;/RequireAny&gt;
&lt;/Limit&gt;
&lt;LimitExcept GET PROPFIND REPORT&gt;
Require valid-user
&lt;/LimitExcept&gt;
RedmineDSN "DBI:Pg:dbname=redmine;host=127.0.0.1" 
RedmineDbUser "redmine"
RedmineDbPass "secret"
&lt;/Location&gt;
@

I tried to isolate the code issue in Redmine.pm and I found it was in sub is_member called by sub authen_handler :

@
sub is_member {
...
my $ret;
PCa DBG OK $ret = 1; <-- CHEAT, IF I UNCOMMENT THIS LINE, I CAN GO TO SVN*

while (my ($hashed_password, $salt, $auth_source_id, $permissions, $project_status) = $sth->fetchrow_array) {
!! PCa DBG KO $ret = 1;  <-- CHEAT, IF I UNCOMMENT THIS LINE, IT IS NOT OK
if ($project_status eq "9" || ($project_status ne "1" && $access_mode eq "W")) {
last;
}
unless ($auth_source_id) {
my $method = $r->method;
my $salted_password = Digest::SHA::sha1_hex($salt.$pass_digest);
if ($hashed_password eq $salted_password && (($access_mode eq "R" && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/) ) {
$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($auth_source_id);
while (my @rowldap = $sthldap->fetchrow_array) {
my $bind_as = $rowldap[3] ? $rowldap[3] : "";
my $bind_pw = $rowldap[4] ? $rowldap[4] : "";
if ($bind_as =~ m/\$login/) { # replace $login with $redmine_user and use $redmine_pass
$bind_as =~ s/\$login/$redmine_user/g;
$bind_pw = $redmine_pass
}
my $ldap = Authen::Simple::LDAP->new(
host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]:$rowldap[1]" : $rowldap[0],
port => $rowldap[1],
basedn => $rowldap[5],
binddn => $bind_as,
bindpw => $bind_pw,
filter => "(".$rowldap[6]."=%s)"
);
my $method = $r->method;
$ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass) && (($access_mode eq "R" && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/));
}
$sthldap->finish();
undef $sthldap;
}
}
!! PCa DBG OK $ret = 1; <-- CHEAT, IF I UNCOMMENT THIS LINE, I CAN GO TO SVN
@

So, I can deduce that the code :
while (my ($hashed_password, $salt, $auth_source_id, $permissions, $project_status) = $sth->fetchrow_array) {
is never done correctly.

I wonder why Redmine.pm requests is bad ?

If I use SVN authentication with password file and mod_ldap (ldap module), the authentication works fine.

I have enable WS repo in Redmine config.

Regards