Project

General

Profile

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

Antonio García-Domínguez, 2010-02-25 10:07

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 require membership with commit 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
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/ match
138
exactly the identifier for some project: /var/www/git/myproject.git won't work,
139
due to the way this module extracts the identifier from the URL.
140
/var/www/git/myproject will work, though. You can put both bare and non-bare
141
repositories in /var/www/git.
142

  
143
Once you have activated this option, you have two options when cloning a
144
repository. Cloning using "http://user@host/git/repo" works, but will ask for
145
the password all the time. To avoid being pestered by password requests, it's
146
best to create a ~/.netrc file with your username and password, and clone using
147
"http://host/git/repo" instead.
148

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

  
154
  touch ~/.netrc
155
  chmod 600 .netrc
156
  echo -e "machine yourhost\nlogin youruser\npassword yourpassword" > ~/.netrc
157

  
96 158
=cut
97 159

  
98 160
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
          }
(3-3/24)