Project

General

Profile

Patch #4905 » 0001-Redmine.pm-update-patch-4905-to-Redmine-1.3.0.patch

Updated patch for Redmine 1.3.0 - Antonio García-Domínguez, 2011-12-22 16:14

View differences:

Redmine.pm
93 93

  
94 94
And you need to upgrade at least reposman.rb (after r860).
95 95

  
96
=head1 GIT SMART HTTP SUPPORT
97

  
98
Git's smart HTTP protocol (available since Git 1.7.0) will not work with the
99
above settings. Redmine.pm normally does access control depending on the HTTP
100
method used: read-only methods are OK for everyone in public projects and
101
members with read rights in private projects. The rest require membership with
102
commit rights in the project.
103

  
104
However, this scheme doesn't work for Git's smart HTTP protocol, as it will use
105
POST even for a simple clone. Instead, read-only requests must be detected using
106
the full URL (including the query string): anything that doesn't belong to the
107
git-receive-pack service is read-only.
108

  
109
To activate this mode of operation, add this line inside your <Location /git>
110
block:
111

  
112
  RedmineGitSmartHttp yes
113

  
114
Here's a sample Apache configuration which integrates git-http-backend with
115
a MySQL database and this new option:
116

  
117
   SetEnv GIT_PROJECT_ROOT /var/www/git/
118
   SetEnv GIT_HTTP_EXPORT_ALL
119
   ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
120
   <Location /git>
121
       Order allow,deny
122
       Allow from all
123

  
124
       AuthType Basic
125
       AuthName Git
126
       Require valid-user
127

  
128
       PerlAccessHandler Apache::Authn::Redmine::access_handler
129
       PerlAuthenHandler Apache::Authn::Redmine::authen_handler
130
       # for mysql
131
       RedmineDSN "DBI:mysql:database=redmine;host=127.0.0.1"
132
       RedmineDbUser "redmine"
133
       RedmineDbPass "xxx"
134
       RedmineGitSmartHttp yes
135
    </Location>
136

  
137
Make sure that all the names of the repositories under /var/www/git/ have a
138
matching identifier for some project: /var/www/git/myproject and
139
/var/www/git/myproject.git will work. You can put both bare and non-bare
140
repositories in /var/www/git, though bare repositories are strongly
141
recommended. You should create them with the rights of the user running Redmine,
142
like this:
143

  
144
  cd /var/www/git
145
  sudo -u user-running-redmine mkdir myproject
146
  cd myproject
147
  sudo -u user-running-redmine git init --bare
148

  
149
Once you have activated this option, you have three options when cloning a
150
repository:
151

  
152
- Cloning using "http://user@host/git/repo(.git)" works, but will ask for the password
153
  all the time.
154

  
155
- Cloning with "http://user:pass@host/git/repo(.git)" does not have this problem, but
156
  this could reveal accidentally your password to the console in some versions
157
  of Git, and you would have to ensure that .git/config is not readable except
158
  by the owner for each of your projects.
159

  
160
- Use "http://host/git/repo(.git)", and store your credentials in the ~/.netrc
161
  file. This is the recommended solution, as you only have one file to protect
162
  and passwords will not be leaked accidentally to the console.
163

  
164
  IMPORTANT NOTE: It is *very important* that the file cannot be read by other
165
  users, as it will contain your password in cleartext. To create the file, you
166
  can use the following commands, replacing yourhost, youruser and yourpassword
167
  with the right values:
168

  
169
    touch ~/.netrc
170
    chmod 600 ~/.netrc
171
    echo -e "machine yourhost\nlogin youruser\npassword yourpassword" > ~/.netrc
172

  
96 173
=cut
97 174

  
98 175
use strict;
......
142 219
    args_how => TAKE1,
143 220
    errmsg => 'RedmineCacheCredsMax must be decimal number',
144 221
  },
222
  {
223
    name => 'RedmineGitSmartHttp',
224
    req_override => OR_AUTHCFG,
225
    args_how => TAKE1,
226
  },
145 227
);
146 228

  
147 229
sub RedmineDSN {
......
179 261
  }
180 262
}
181 263

  
264
sub RedmineGitSmartHttp {
265
  my ($self, $parms, $arg) = @_;
266
  $arg = lc $arg;
267

  
268
  if ($arg eq "yes" || $arg eq "true") {
269
    $self->{RedmineGitSmartHttp} = 1;
270
  } else {
271
    $self->{RedmineGitSmartHttp} = 0;
272
  }
273
}
274

  
182 275
sub trim {
183 276
  my $string = shift;
184 277
  $string =~ s/\s{2,}/ /g;
......
195 288

  
196 289
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
197 290

  
291
sub request_is_read_only {
292
  my ($r) = @_;
293
  my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
294

  
295
  # Do we use Git's smart HTTP protocol, or not?
296
  if (defined $cfg->{RedmineGitSmartHttp} and $cfg->{RedmineGitSmartHttp}) {
297
    my $uri = $r->unparsed_uri;
298
    my $location = $r->location;
299
    my $is_read_only = $uri !~ m{^$location/*[^/]+/+(info/refs\?service=)?git\-receive\-pack$}o;
300
    return $is_read_only;
301
  } else {
302
    # Old behaviour: check the HTTP method
303
    my $method = $r->method;
304
    return defined $read_only_methods{$method};
305
  }
306
}
307

  
198 308
sub access_handler {
199 309
  my $r = shift;
200 310

  
......
203 313
      return FORBIDDEN;
204 314
  }
205 315

  
206
  my $method = $r->method;
207
  return OK unless defined $read_only_methods{$method};
316
  return OK unless request_is_read_only($r);
208 317

  
209 318
  my $project_id = get_project_identifier($r);
210 319

  
......
329 438

  
330 439
  my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass);
331 440

  
332
  my $access_mode = defined $read_only_methods{$r->method} ? "R" : "W";
441
  my $access_mode = request_is_ready_only($r) ? "R" : "W";
333 442

  
334 443
  my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
335 444
  my $usrprojpass;
......
400 509

  
401 510
    my $location = $r->location;
402 511
    my ($identifier) = $r->uri =~ m{$location/*([^/]+)};
512
    $identifier =~ s/\.git//;
403 513
    $identifier;
404 514
}
405 515

  
(13-13/24)