# -*- coding: binary -*-

module Msf::Exploit::Remote::HTTP::Moodle::Login
  # performs a moodle login
  #
  # @param user [String] Username
  # @param pass [String] Password
  # @param timeout [Integer] The maximum number of seconds to wait before the request times out
  # @return [HttpCookie,nil] the session cookies as a single string on successful login, nil otherwise
  def moodle_login(user, pass, timeout = 20)
    res = send_request_cgi({
      'uri' => moodle_url_login,
      'keep_cookies' => true
    }, timeout)
    return nil unless res

    res.body =~ /name="logintoken" value="([^"]+)">/

    res = send_request_cgi!({
      'method' => 'POST',
      'uri' => moodle_url_login,
      'vars_post' => moodle_helper_login_post_data(user, pass, Regexp.last_match(1)),
      'keep_cookies' => true
    }, timeout, 20) # typical redirect is 3-5, but it may do more if caching gets messed up on server

    if !res || (res.code != 200) || !res.body.include?('<title>Dashboard</title>')
      return nil
    end

    cookies = cookie_jar.cookies
    cookie_jar.clear
    store_valid_credential(user: user, private: pass)
    return cookies
  end

  # performs a loginas moodle account impersonation
  #
  # @param course_id [String] ID of the course the user is registered in
  # @param user_id [String] User ID of the user to impersonate
  # @param session_key [String] session key for the current session
  # @return [HttpResponse,nil] the HttpResponse object on successful impersonation, nil otherwise
  def moodle_loginas(course_id, user_id, session_key, timeout = 20)
    res = send_request_cgi({
      'uri' => moodle_url_loginas,
      'vars_get' => moodle_helper_loginas_get_data(course_id, user_id, session_key),
      'keep_cookies' => true
    }, timeout)
    return nil unless res

    # click the 'continue' button
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, 'course', 'view.php'),
      'vars_get' =>
          {
            'id' => course_id
          },
      'keep_cookies' => true
    })
    return nil unless res

    res
  end
end
