Skip to content

Commit ac96ab7

Browse files
author
root
committed
1 parent c942749 commit ac96ab7

File tree

1 file changed

+74
-59
lines changed

1 file changed

+74
-59
lines changed

Diff for: app/controllers/git_http_controller.rb

+74-59
Original file line numberDiff line numberDiff line change
@@ -15,59 +15,60 @@ def index
1515

1616
@request = Rack::Request.new(request.env)
1717

18-
command, @git_repo_path, @requested_file, @rpc = match_routing
18+
command, @requested_file, @rpc = match_routing(@request)
1919

2020
return render_method_not_allowed if command == 'not_allowed'
2121
return render_not_found if !command
2222

23-
# strip HTTP prefix
24-
@git_repo_path = @git_repo_path.sub(params[:prefix], '')
25-
2623
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}"
3127
if !@user.nil?
32-
logger.info "user_name : #{@user.login}"
28+
logger.info "user_name : #{@user.login}"
29+
@authenticated = true
3330
else
34-
logger.info "user_name : anonymous (project is public)"
31+
logger.info "user_name : anonymous (project is public)"
32+
@authenticated = false
3533
end
36-
logger.info "command : #{command}"
34+
3735
logger.info "##########################"
3836

3937
self.method(command).call()
4038

4139
end
4240

41+
4342
private
4443

44+
4545
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')
4949

5050
query_valid = false
5151
authentication_valid = true
5252

5353
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}"
5657
logger.info "############################"
5758

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)
5960
if (@project = @repository.project) && @repository.extra[:git_http] != 0
6061
allow_anonymous_read = @project.is_public
6162
# Push requires HTTP enabled or valid SSL
6263
# 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
6465
query_valid = true
65-
if @is_push || (!allow_anonymous_read)
66+
if is_push || (!allow_anonymous_read)
6667
authentication_valid = false
6768
authenticate_or_request_with_http_basic do |login, password|
6869
@user = User.find_by_login(login);
6970
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 ))
7172
authentication_valid = @user.check_password?(password)
7273
end
7374
end
@@ -99,15 +100,12 @@ def get_enumerator
99100

100101

101102
def service_rpc
103+
return render_no_access if !has_access(@rpc, true)
104+
102105
input = read_body
103106

104107
command = git_command("#{@rpc} --stateless-rpc .")
105108

106-
logger.info "###### SERVICE RPC ######"
107-
logger.info "command : #{command}"
108-
logger.debug "input data : #{input}"
109-
logger.info "#########################"
110-
111109
self.response.headers["Content-Type"] = "application/x-git-%s-result" % @rpc
112110
self.response.status = 200
113111

@@ -145,17 +143,11 @@ def service_rpc
145143
def get_info_refs
146144
service_name = get_service_type
147145

148-
if service_name
146+
if has_access(service_name)
149147
command = git_command("#{service_name} --stateless-rpc --advertise-refs .")
150148
refs = %x[#{command}]
151-
content_type = "application/x-git-#{service_name}-advertisement"
152149

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"
159151

160152
self.response.status = 200
161153
self.response.headers["Content-Type"] = content_type
@@ -225,6 +217,8 @@ def get_text_file
225217
# logic helping functions
226218
# ------------------------
227219

220+
VALID_SERVICE_TYPES = ['upload-pack', 'receive-pack']
221+
228222
SERVICES = [
229223
["POST", 'service_rpc', "/(.*?)/git-upload-pack$", 'upload-pack'],
230224
["POST", 'service_rpc', "/(.*?)/git-receive-pack$", 'receive-pack'],
@@ -240,41 +234,54 @@ def get_text_file
240234
["GET", 'get_idx_file', "/(.*?)/objects/pack/pack-[0-9a-f]{40}\\.idx$"],
241235
]
242236

243-
def match_routing
244-
cmd = nil
237+
def match_routing(request)
238+
cmd = nil
245239
path = nil
240+
file = nil
241+
246242
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
249245
cmd = handler
250246
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
252252

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 "##########################"
259253

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
261259
end
262260
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)
264268
end
265269

266270

267-
# some of this borrowed from the Rack::File implementation
268271
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}"
269275

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
271281

272282
last_modified = File.mtime(requested_file).httpdate
273283
file_size = File.size?(requested_file)
274284

275-
logger.info "###### SEND FILE ######"
276-
logger.info "requested_file : #{requested_file}"
277-
logger.info "content_type : #{content_type}"
278285
logger.info "last_modified : #{last_modified}"
279286
logger.info "file_size : #{file_size}"
280287
logger.info "#######################"
@@ -284,7 +291,6 @@ def internal_send_file(requested_file, content_type)
284291
self.response.status = 200
285292
self.response.headers["Last-Modified"] = last_modified
286293
self.response.headers["Content-Length"] = file_size.to_s
287-
#~ cache_parameter
288294

289295
send_file requested_file, :type => content_type
290296

@@ -317,9 +323,15 @@ def file_exists(requested_file)
317323
end
318324

319325

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!
321333
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)} ;"
323335
end
324336

325337

@@ -330,6 +342,7 @@ def is_ssl?
330342

331343
def read_body
332344
enc_header = (request.headers['HTTP_CONTENT_ENCODING']).to_s
345+
333346
if enc_header =~ /gzip/
334347
input = Zlib::GzipReader.new(request.body).read
335348
else
@@ -352,7 +365,7 @@ def get_config_setting(service_name)
352365
if service_name == 'uploadpack'
353366
return setting != 'false'
354367
else
355-
return setting == 'true'
368+
return @authenticated
356369
end
357370
end
358371

@@ -369,10 +382,6 @@ def update_server_info
369382
end
370383

371384

372-
def git_command(command)
373-
return "#{run_git_prefix()} env GL_BYPASS_UPDATE_HOOK=true git #{command} '"
374-
end
375-
376385
# --------------------------------------
377386
# HTTP error response handling functions
378387
# --------------------------------------
@@ -390,14 +399,17 @@ def render_method_not_allowed
390399
return head
391400
end
392401

402+
393403
def render_not_found
394404
head :not_found
395405
end
396406

407+
397408
def render_no_access
398409
head :forbidden
399410
end
400411

412+
401413
# ------------------------------
402414
# packet-line handling functions
403415
# ------------------------------
@@ -406,6 +418,7 @@ def pkt_flush
406418
'0000'
407419
end
408420

421+
409422
def pkt_write(str)
410423
(str.size + 4).to_s(base=16).rjust(4, '0') + str
411424
end
@@ -421,13 +434,15 @@ def hdr_nocache
421434
self.response.headers["Cache-Control"] = "no-cache, max-age=0, must-revalidate"
422435
end
423436

437+
424438
def hdr_cache_forever
425439
now = Time.now().to_i
426440
self.response.headers["Date"] = now.to_s
427441
self.response.headers["Expires"] = (now + 31536000).to_s;
428442
self.response.headers["Cache-Control"] = "public, max-age=31536000";
429443
end
430444

445+
431446
def logger
432447
Rails.logger
433448
end

0 commit comments

Comments
 (0)