2020-03-13 15:44:24 +05:30
# frozen_string_literal: true
module Repositories
class GitHttpClientController < Repositories :: ApplicationController
include ActionController :: HttpAuthentication :: Basic
2022-10-11 01:57:18 +05:30
include KerberosHelper
2020-03-13 15:44:24 +05:30
include Gitlab :: Utils :: StrongMemoize
2021-01-29 00:20:46 +05:30
attr_reader :authentication_result , :redirected_path
2020-03-13 15:44:24 +05:30
2022-01-26 12:08:38 +05:30
delegate :authentication_abilities , to : :authentication_result , allow_nil : true
2020-03-13 15:44:24 +05:30
delegate :type , to : :authentication_result , allow_nil : true , prefix : :auth_result
# Git clients will not know what authenticity token to send along
skip_around_action :set_session_storage
skip_before_action :verify_authenticity_token
2020-07-01 16:08:20 +05:30
prepend_before_action :authenticate_user , :parse_repo_path
2020-03-13 15:44:24 +05:30
2022-04-04 11:22:00 +05:30
skip_around_action :sessionless_bypass_admin_mode!
around_action :bypass_admin_mode! , if : :authenticated_user
2021-01-03 14:25:43 +05:30
feature_category :source_code_management
2022-01-26 12:08:38 +05:30
def authenticated_user
authentication_result & . user || authentication_result & . deploy_token
end
2020-03-13 15:44:24 +05:30
private
2022-01-26 12:08:38 +05:30
def user
authenticated_user
end
2020-03-13 15:44:24 +05:30
def download_request?
raise NotImplementedError
end
def upload_request?
raise NotImplementedError
end
def authenticate_user
2021-10-27 15:23:28 +05:30
@authentication_result = Gitlab :: Auth :: Result :: EMPTY
2020-03-13 15:44:24 +05:30
if allow_basic_auth? && basic_auth_provided?
login , password = user_name_and_password ( request )
if handle_basic_authentication ( login , password )
return # Allow access
end
2022-10-11 01:57:18 +05:30
elsif allow_kerberos_auth? && spnego_provided?
2020-03-13 15:44:24 +05:30
kerberos_user = find_kerberos_user
if kerberos_user
@authentication_result = Gitlab :: Auth :: Result . new (
kerberos_user , nil , :kerberos , Gitlab :: Auth . full_authentication_abilities )
send_final_spnego_response
return # Allow access
end
elsif http_download_allowed?
@authentication_result = Gitlab :: Auth :: Result . new ( nil , project , :none , [ :download_code ] )
return # Allow access
end
send_challenges
2022-09-01 20:07:04 +05:30
render_access_denied
2020-03-13 15:44:24 +05:30
rescue Gitlab :: Auth :: MissingPersonalAccessTokenError
2022-09-01 20:07:04 +05:30
render_access_denied
end
def render_access_denied
help_page = help_page_url (
'topics/git/troubleshooting_git' ,
anchor : 'error-on-git-fetch-http-basic-access-denied'
)
render (
plain : format ( _ ( " HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url} " ) , help_page_url : help_page ) ,
status : :unauthorized
)
2020-03-13 15:44:24 +05:30
end
def basic_auth_provided?
has_basic_credentials? ( request )
end
def send_challenges
challenges = [ ]
challenges << 'Basic realm="GitLab"' if allow_basic_auth?
2022-10-11 01:57:18 +05:30
challenges << spnego_challenge if allow_kerberos_auth?
2020-03-13 15:44:24 +05:30
headers [ 'Www-Authenticate' ] = challenges . join ( " \n " ) if challenges . any?
end
2021-01-29 00:20:46 +05:30
def container
parse_repo_path unless defined? ( @container )
@container
end
2020-03-13 15:44:24 +05:30
def project
parse_repo_path unless defined? ( @project )
@project
end
2021-02-22 17:27:13 +05:30
def repository_path
@repository_path || = params [ :repository_path ]
end
2020-03-13 15:44:24 +05:30
def parse_repo_path
2021-02-22 17:27:13 +05:30
@container , @project , @repo_type , @redirected_path = Gitlab :: RepoPath . parse ( repository_path )
2020-03-13 15:44:24 +05:30
end
def repository
strong_memoize ( :repository ) do
2020-04-08 14:13:33 +05:30
repo_type . repository_for ( container )
2020-03-13 15:44:24 +05:30
end
end
def repo_type
parse_repo_path unless defined? ( @repo_type )
@repo_type
end
def handle_basic_authentication ( login , password )
@authentication_result = Gitlab :: Auth . find_for_git_client (
login , password , project : project , ip : request . ip )
@authentication_result . success?
end
def ci?
authentication_result . ci? ( project )
end
def http_download_allowed?
Gitlab :: ProtocolAccess . allowed? ( 'http' ) &&
download_request? &&
2020-04-08 14:13:33 +05:30
container &&
Guest . can? ( repo_type . guest_read_ability , container )
2020-03-13 15:44:24 +05:30
end
2022-04-04 11:22:00 +05:30
def bypass_admin_mode! ( & block )
return yield unless Gitlab :: CurrentSettings . admin_mode
Gitlab :: Auth :: CurrentUserMode . bypass_session! ( authenticated_user . id , & block )
end
2020-03-13 15:44:24 +05:30
end
end
2021-06-08 01:23:25 +05:30
Repositories :: GitHttpClientController . prepend_mod_with ( 'Repositories::GitHttpClientController' )