# -*- coding: binary -*-

module Msf::Exploit::Remote::HTTP::Nifi::Auth
  include Msf::Exploit::Remote::HttpClient

  # Determines if the Apache Nifi instance supports login.
  #
  # @return the value of supportsLogin from the server, nil on error
  def supports_login?
    vprint_status('Attempting to retrieve access configuration')
    res = send_request_cgi({
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'nifi-api', 'access', 'config')
    })

    if res.nil?
      print_bad("#{peer} - Could not connect to web service - no response")
      return nil
    end

    unless res.code == 200
      print_bad("Unexpected response code: #{res.code}")
      return nil
    end
    res.get_json_document.dig('config', 'supportsLogin')
  end

  # Attempts a login with username and password to retrieve a bearer token for APIs
  #
  # @return [String] The bearer token on successful login, nil on errors
  def retrieve_login_token
    vprint_status('Attempting to login')
    res = send_request_cgi(
      {
        'method' => 'POST',
        'uri' => normalize_uri(target_uri.path, 'nifi-api', 'access', 'token'),
        'vars_post' => {
          'username' => datastore['USERNAME'],
          'password' => datastore['PASSWORD']
        }
      }
    )
    if res.nil?
      print_bad("#{peer} - Could not connect to web service - no response")
      return nil
    end

    if res.code == 400
      print_bad('Invalid Credentials')
      return nil
    elsif res.code != 201
      print_bad("Unexpected response code: #{res.code}")
      return nil
    end
    res.body
  end
end
