# frozen_string_literal: true module Msf module OptionalSession module LDAP include Msf::OptionalSession RHOST_GROUP_OPTIONS = %w[RHOSTS RPORT LDAPDomain LDAPUsername LDAPPassword THREADS] REQUIRED_OPTIONS = %w[RHOSTS RPORT THREADS] def initialize(info = {}) super( update_info( info, 'SessionTypes' => %w[ldap] ) ) if optional_session_enabled? register_option_group(name: 'SESSION', description: 'Used when connecting via an existing SESSION', option_names: ['SESSION']) register_option_group(name: 'RHOST', description: 'Used when making a new connection via RHOSTS', option_names: RHOST_GROUP_OPTIONS, required_options: REQUIRED_OPTIONS) register_options( [ Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]), Msf::Opt::RHOST(nil, false), Msf::Opt::RPORT(389, false) ] ) add_info('New in Metasploit 6.4 - This module can target a %grnSESSION%clr or an %grnRHOST%clr') end end def optional_session_enabled? framework.features.enabled?(Msf::FeatureManager::LDAP_SESSION_TYPE) end # @see #ldap_open # @return [Object] The result of whatever the block that was # passed in via the "block" parameter yielded. def ldap_connect(opts = {}, &block) if session && !opts[:base].blank? session.client.base = opts[:base] end return yield session.client if session ldap_open(get_connect_opts.merge(opts), &block) rescue ::StandardError => e handle_error(e) end # Create a new LDAP connection using Rex::Proto::LDAP::Client.new and yield the # resulting connection object to the caller of this method. # # @param opts [Hash] A hash containing the connection options for the # LDAP connection to the target server. # @yieldparam ldap [Rex::Proto::LDAP::Client] The LDAP connection handle to use for connecting to # the target LDAP server. def ldap_new(opts = {}) if session && !opts[:base].blank? session.client.base = opts[:base] end return yield session.client if session super rescue ::StandardError => e handle_error(e) end private def handle_error(e) case e when ::Net::LDAP::ResponseMissingOrInvalidError elog("LDAP Client response missing or invalid: #{e.class}", error: e) if session print_error("Killing session #{session.sid} due to missing or invalid response from the server.") session.kill end else elog("LDAP Client: #{e.class}", error: e) # Re-raise other exceptions so they can be handled elsewhere raise e end end end end end