class Epp::SessionsController < EppController skip_authorization_check only: [:hello, :login, :logout] def hello render_epp_response('greeting') end # rubocop: disable Metrics/PerceivedComplexity # rubocop: disable Metrics/CyclomaticComplexity # rubocop: disable Metrics/MethodLength # rubocop: disable Metrics/AbcSize def login success = true @api_user = ApiUser.find_by(login_params) webclient_request = ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip) if webclient_request && !Rails.env.test? && !Rails.env.development? client_md5 = Certificate.parse_md_from_string(request.env['HTTP_SSL_CLIENT_CERT']) server_md5 = Certificate.parse_md_from_string(File.read(ENV['cert_path'])) if client_md5 != server_md5 epp_errors << { msg: 'Authentication error; server closing connection (certificate is not valid)', code: '2501' } success = false end end if !webclient_request && @api_user unless @api_user.api_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) epp_errors << { msg: 'Authentication error; server closing connection (certificate is not valid)', code: '2501' } success = false end end if success && !@api_user epp_errors << { msg: 'Authentication error; server closing connection (API user not found)', code: '2501' } success = false end if success && !@api_user.try(:active) epp_errors << { msg: 'Authentication error; server closing connection (API user is not active)', code: '2501' } success = false end if success && !ip_white? epp_errors << { msg: 'Authentication error; server closing connection (IP is not whitelisted)', code: '2501' } success = false end if success && !connection_limit_ok? epp_errors << { msg: 'Authentication error; server closing connection (connection limit reached)', code: '2501' } success = false end if success if params[:parsed_frame].css('newPW').first unless @api_user.update(password: params[:parsed_frame].css('newPW').first.text) response.headers['X-EPP-Returncode'] = '2500' handle_errors(@api_user) and return end end epp_session[:api_user_id] = @api_user.id epp_session.update_column(:registrar_id, @api_user.registrar_id) render_epp_response('login_success') else response.headers['X-EPP-Returncode'] = '2500' handle_errors end end # rubocop: enable Metrics/MethodLength # rubocop: enable Metrics/AbcSize # rubocop: enable Metrics/PerceivedComplexity # rubocop: enable Metrics/CyclomaticComplexity def ip_white? webclient_request = ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip) return true if webclient_request if @api_user return false unless @api_user.registrar.api_ip_white?(request.ip) end true end def connection_limit_ok? return true if Rails.env.test? || Rails.env.development? c = EppSession.where( 'registrar_id = ? AND updated_at >= ?', @api_user.registrar_id, Time.zone.now - 5.minutes ).count return false if c >= 4 true end def logout @api_user = current_user # cache current_user for logging epp_session.destroy response.headers['X-EPP-Returncode'] = '1500' render_epp_response('logout') end ### HELPER METHODS ### def login_params user = params[:parsed_frame].css('clID').first.text pw = params[:parsed_frame].css('pw').first.text { username: user, password: pw } end end