@@ -15,59 +15,60 @@ def index
15
15
16
16
@request = Rack ::Request . new ( request . env )
17
17
18
- command , @git_repo_path , @ requested_file, @rpc = match_routing
18
+ command , @requested_file , @rpc = match_routing ( @request )
19
19
20
20
return render_method_not_allowed if command == 'not_allowed'
21
21
return render_not_found if !command
22
22
23
- # strip HTTP prefix
24
- @git_repo_path = @git_repo_path . sub ( params [ :prefix ] , '' )
25
-
26
23
logger . info "###### AUTHENTICATED ######"
27
- logger . info "project name : #{ @project . identifier } "
28
- logger . info "repository dir : #{ @repository . url } "
29
- logger . info "repository path: #{ @git_repo_path } "
30
- logger . info "is_push : #{ @is_push } "
24
+ logger . info "project name : #{ @project . identifier } "
25
+ logger . info "repository dir : #{ @repository . url } "
26
+ logger . info "command : #{ command } "
31
27
if !@user . nil?
32
- logger . info "user_name : #{ @user . login } "
28
+ logger . info "user_name : #{ @user . login } "
29
+ @authenticated = true
33
30
else
34
- logger . info "user_name : anonymous (project is public)"
31
+ logger . info "user_name : anonymous (project is public)"
32
+ @authenticated = false
35
33
end
36
- logger . info "command : #{ command } "
34
+
37
35
logger . info "##########################"
38
36
39
37
self . method ( command ) . call ( )
40
38
41
39
end
42
40
41
+
43
42
private
44
43
44
+
45
45
def authenticate
46
- # fixme: rails3 route blobbing will not convert *other to array
47
- params [ :path ] = params [ :path ] . split ( "/" )
48
- @ is_push = ( params [ :path ] [ 0 ] == " git-receive-pack" || params [ :service ] == " git-receive-pack" )
46
+ git_params = params [ :git_params ] . split ( '/' )
47
+ repo_path = params [ :repo_path ]
48
+ is_push = ( git_params [ 0 ] == ' git-receive-pack' || params [ :service ] == ' git-receive-pack' )
49
49
50
50
query_valid = false
51
51
authentication_valid = true
52
52
53
53
logger . info "###### AUTHENTICATION ######"
54
- logger . info "param : #{ params [ :path ] } "
55
- logger . info "is_push : #{ @is_push } "
54
+ logger . info "git_params : #{ git_params } "
55
+ logger . info "repo_path : #{ repo_path } "
56
+ logger . info "is_push : #{ is_push } "
56
57
logger . info "############################"
57
58
58
- if ( @repository = Repository . find_by_path ( params [ : repo_path] , :parse_ext => true ) ) && @repository . is_a? ( Repository ::Git )
59
+ if ( @repository = Repository . find_by_path ( repo_path , :parse_ext => true ) ) && @repository . is_a? ( Repository ::Git )
59
60
if ( @project = @repository . project ) && @repository . extra [ :git_http ] != 0
60
61
allow_anonymous_read = @project . is_public
61
62
# Push requires HTTP enabled or valid SSL
62
63
# Read is ok over HTTP for public projects
63
- if @repository . extra [ :git_http ] == 2 || ( @repository . extra [ :git_http ] == 1 && is_ssl? ) || !@ is_push && allow_anonymous_read
64
+ if @repository . extra [ :git_http ] == 2 || ( @repository . extra [ :git_http ] == 1 && is_ssl? ) || !is_push && allow_anonymous_read
64
65
query_valid = true
65
- if @ is_push || ( !allow_anonymous_read )
66
+ if is_push || ( !allow_anonymous_read )
66
67
authentication_valid = false
67
68
authenticate_or_request_with_http_basic do |login , password |
68
69
@user = User . find_by_login ( login ) ;
69
70
if @user . is_a? ( User )
70
- if @user . allowed_to? ( :commit_access , @project ) || ( ( !@ is_push) && @user . allowed_to? ( :view_changesets , @project ) )
71
+ if @user . allowed_to? ( :commit_access , @project ) || ( ( !is_push ) && @user . allowed_to? ( :view_changesets , @project ) )
71
72
authentication_valid = @user . check_password? ( password )
72
73
end
73
74
end
@@ -99,15 +100,12 @@ def get_enumerator
99
100
100
101
101
102
def service_rpc
103
+ return render_no_access if !has_access ( @rpc , true )
104
+
102
105
input = read_body
103
106
104
107
command = git_command ( "#{ @rpc } --stateless-rpc ." )
105
108
106
- logger . info "###### SERVICE RPC ######"
107
- logger . info "command : #{ command } "
108
- logger . debug "input data : #{ input } "
109
- logger . info "#########################"
110
-
111
109
self . response . headers [ "Content-Type" ] = "application/x-git-%s-result" % @rpc
112
110
self . response . status = 200
113
111
@@ -145,17 +143,11 @@ def service_rpc
145
143
def get_info_refs
146
144
service_name = get_service_type
147
145
148
- if service_name
146
+ if has_access ( service_name )
149
147
command = git_command ( "#{ service_name } --stateless-rpc --advertise-refs ." )
150
148
refs = %x[#{ command } ]
151
- content_type = "application/x-git-#{ service_name } -advertisement"
152
149
153
- logger . info "###### GET INFO REFS ######"
154
- logger . info "command : #{ command } "
155
- logger . info "refs : #{ refs } "
156
- logger . info "content_type : #{ content_type } "
157
- logger . info "service_name : #{ service_name } "
158
- logger . info "###########################"
150
+ content_type = "application/x-git-#{ service_name } -advertisement"
159
151
160
152
self . response . status = 200
161
153
self . response . headers [ "Content-Type" ] = content_type
@@ -225,6 +217,8 @@ def get_text_file
225
217
# logic helping functions
226
218
# ------------------------
227
219
220
+ VALID_SERVICE_TYPES = [ 'upload-pack' , 'receive-pack' ]
221
+
228
222
SERVICES = [
229
223
[ "POST" , 'service_rpc' , "/(.*?)/git-upload-pack$" , 'upload-pack' ] ,
230
224
[ "POST" , 'service_rpc' , "/(.*?)/git-receive-pack$" , 'receive-pack' ] ,
@@ -240,41 +234,54 @@ def get_text_file
240
234
[ "GET" , 'get_idx_file' , "/(.*?)/objects/pack/pack-[0-9a-f]{40}\\ .idx$" ] ,
241
235
]
242
236
243
- def match_routing
244
- cmd = nil
237
+ def match_routing ( request )
238
+ cmd = nil
245
239
path = nil
240
+ file = nil
241
+
246
242
SERVICES . each do |method , handler , match , rpc |
247
- if m = Regexp . new ( match ) . match ( @ request. path_info )
248
- return [ 'not_allowed' ] if method != @ request. request_method
243
+ if m = Regexp . new ( match ) . match ( request . path_info )
244
+ return [ 'not_allowed' ] if method != request . request_method
249
245
cmd = handler
250
246
path = m [ 1 ]
251
- file = @request . path_info . sub ( path + '/' , '' )
247
+ file = request . path_info . sub ( path + '/' , '' )
248
+ return [ cmd , file , rpc ]
249
+ end
250
+ end
251
+ end
252
252
253
- logger . info "######## ROUTING #########"
254
- logger . info "path : #{ path } "
255
- logger . info "path info : #{ @request . path_info } "
256
- logger . info "file : #{ file } "
257
- logger . info "rpc : #{ rpc } "
258
- logger . info "##########################"
259
253
260
- return [ cmd , path , file , rpc ]
254
+ def has_access ( rpc , check_content_type = false )
255
+ if check_content_type
256
+ if request . content_type != "application/x-git-%s-request" % rpc
257
+ logger . error "[GitHosting] Invalid content type #{ request . content_type } "
258
+ return false
261
259
end
262
260
end
263
- return nil
261
+
262
+ if !VALID_SERVICE_TYPES . include? rpc
263
+ logger . error "[GitHosting] Invalid service type #{ rpc } "
264
+ return false
265
+ end
266
+
267
+ return get_config_setting ( rpc )
264
268
end
265
269
266
270
267
- # some of this borrowed from the Rack::File implementation
268
271
def internal_send_file ( requested_file , content_type )
272
+ logger . info "###### SEND FILE ######"
273
+ logger . info "requested_file : #{ requested_file } "
274
+ logger . info "content_type : #{ content_type } "
269
275
270
- return render_not_found if !File . exists? ( requested_file )
276
+ if !File . exists? ( requested_file )
277
+ logger . info "error : File not found!"
278
+ logger . info "#######################"
279
+ return render_not_found
280
+ end
271
281
272
282
last_modified = File . mtime ( requested_file ) . httpdate
273
283
file_size = File . size? ( requested_file )
274
284
275
- logger . info "###### SEND FILE ######"
276
- logger . info "requested_file : #{ requested_file } "
277
- logger . info "content_type : #{ content_type } "
278
285
logger . info "last_modified : #{ last_modified } "
279
286
logger . info "file_size : #{ file_size } "
280
287
logger . info "#######################"
@@ -284,7 +291,6 @@ def internal_send_file(requested_file, content_type)
284
291
self . response . status = 200
285
292
self . response . headers [ "Last-Modified" ] = last_modified
286
293
self . response . headers [ "Content-Length" ] = file_size . to_s
287
- #~ cache_parameter
288
294
289
295
send_file requested_file , :type => content_type
290
296
@@ -317,9 +323,15 @@ def file_exists(requested_file)
317
323
end
318
324
319
325
320
- #note command needs to be terminated with a quote!
326
+ ## Note: command must be terminated with a quote!
327
+ def git_command ( command )
328
+ return "#{ run_git_prefix ( ) } env GL_BYPASS_UPDATE_HOOK=true git #{ command } '"
329
+ end
330
+
331
+
332
+ ## Note: command must be started with a quote!
321
333
def run_git_prefix
322
- return "#{ GitHosting :: git_user_runner ( ) } 'cd #{ GitHostingConf . repository_base } #{ @git_repo_path } ; "
334
+ return "#{ GitHosting . git_user_runner } 'cd #{ GitHosting . repository_path ( @repository ) } ;"
323
335
end
324
336
325
337
@@ -330,6 +342,7 @@ def is_ssl?
330
342
331
343
def read_body
332
344
enc_header = ( request . headers [ 'HTTP_CONTENT_ENCODING' ] ) . to_s
345
+
333
346
if enc_header =~ /gzip/
334
347
input = Zlib ::GzipReader . new ( request . body ) . read
335
348
else
@@ -352,7 +365,7 @@ def get_config_setting(service_name)
352
365
if service_name == 'uploadpack'
353
366
return setting != 'false'
354
367
else
355
- return setting == 'true'
368
+ return @authenticated
356
369
end
357
370
end
358
371
@@ -369,10 +382,6 @@ def update_server_info
369
382
end
370
383
371
384
372
- def git_command ( command )
373
- return "#{ run_git_prefix ( ) } env GL_BYPASS_UPDATE_HOOK=true git #{ command } '"
374
- end
375
-
376
385
# --------------------------------------
377
386
# HTTP error response handling functions
378
387
# --------------------------------------
@@ -390,14 +399,17 @@ def render_method_not_allowed
390
399
return head
391
400
end
392
401
402
+
393
403
def render_not_found
394
404
head :not_found
395
405
end
396
406
407
+
397
408
def render_no_access
398
409
head :forbidden
399
410
end
400
411
412
+
401
413
# ------------------------------
402
414
# packet-line handling functions
403
415
# ------------------------------
@@ -406,6 +418,7 @@ def pkt_flush
406
418
'0000'
407
419
end
408
420
421
+
409
422
def pkt_write ( str )
410
423
( str . size + 4 ) . to_s ( base = 16 ) . rjust ( 4 , '0' ) + str
411
424
end
@@ -421,13 +434,15 @@ def hdr_nocache
421
434
self . response . headers [ "Cache-Control" ] = "no-cache, max-age=0, must-revalidate"
422
435
end
423
436
437
+
424
438
def hdr_cache_forever
425
439
now = Time . now ( ) . to_i
426
440
self . response . headers [ "Date" ] = now . to_s
427
441
self . response . headers [ "Expires" ] = ( now + 31536000 ) . to_s ;
428
442
self . response . headers [ "Cache-Control" ] = "public, max-age=31536000" ;
429
443
end
430
444
445
+
431
446
def logger
432
447
Rails . logger
433
448
end
0 commit comments