Project

General

Profile

Patch #4905 » 0001-Redmine.pm-add-Git-smart-HTTP-support-v2.patch

Antonio García-Domínguez, 2010-02-24 17:59

View differences:

extra/svn/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 will not work with the above settings. Redmine.pm
99
normally does access control depending on the HTTP method used: read-only
100
methods are OK for everyone in public projects and members with read rights
101
in private projects. The rest all require membership with write rights in the
102
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
106
using the full URL (including the query string): anything that doesn't belong
107
to the 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
Once you have activated this option, you have two options when cloning a
115
repository. Cloning using "http://user@host/git/repo" works, but will ask for
116
the password all the time. To avoid being pestered by password requests, it's
117
best to create a ~/.netrc file with your username and password, and clone using
118
"http://host/git/repo" instead.
119

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

  
125
  touch ~/.netrc
126
  chmod 600 .netrc
127
  echo -e "machine yourhost\nlogin youruser\npassword yourpassword" > ~/.netrc
128

  
96 129
=cut
97 130

  
98 131
use strict;
......
142 174
    args_how => TAKE1,
143 175
    errmsg => 'RedmineCacheCredsMax must be decimal number',
144 176
  },
177
  {
178
    name => 'RedmineGitSmartHttp',
179
    req_override => OR_AUTHCFG,
180
    args_how => TAKE1,
181
  },
145 182
);
146 183

  
147 184
sub RedmineDSN { 
......
178 215
  }
179 216
}
180 217

  
218
sub RedmineGitSmartHttp {
219
  my ($self, $parms, $arg) = @_;
220
  $arg = lc $arg;
221

  
222
  if ($arg eq "yes" || $arg eq "true") {
223
    $self->{RedmineGitSmartHttp} = 1;
224
  } else {
225
    $self->{RedmineGitSmartHttp} = 0;
226
  }
227
}
228

  
181 229
sub trim {
182 230
  my $string = shift;
183 231
  $string =~ s/\s{2,}/ /g;
......
191 239

  
192 240
Apache2::Module::add(__PACKAGE__, \@directives);
193 241

  
194 242

  
195 243
my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/;
196 244

  
245
sub request_is_read_only {
246
  my ($r) = @_;
247
  my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
248

  
249
  # Do we use Git's smart HTTP protocol, or not?
250
  if (defined $cfg->{RedmineGitSmartHttp} and $cfg->{RedmineGitSmartHttp}) {
251
    my $uri = $r->unparsed_uri;
252
    my $is_read_only = $uri !~ /^\/git\/.*\/[^\/]*git\-receive\-pack$/o;
253
    return $is_read_only;
254
  } else {
255
    # Old behaviour: check the HTTP method
256
    my $method = $r->method;
257
    return defined $read_only_methods{$method};
258
  }
259
}
260

  
197 261
sub access_handler {
198 262
  my $r = shift;
199 263

  
......
202 265
      return FORBIDDEN;
203 266
  }
204 267

  
205
  my $method = $r->method;
206
  return OK unless defined $read_only_methods{$method};
268
  return OK unless request_is_read_only($r);
207 269

  
208 270
  my $project_id = get_project_identifier($r);
209 271

  
......
291 353

  
292 354
      unless ($auth_source_id) {
293 355
	  my $method = $r->method;
294
          if ($hashed_password eq $pass_digest && ((defined $read_only_methods{$method} && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/) ) {
356
          if ($hashed_password eq $pass_digest && ((request_is_read_only($r) && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/) ) {
295 357
              $ret = 1;
296 358
              last;
297 359
          }
(2-2/24)