require 'msf/base'

module Msf
module Simple

###
#
# A simplified exploit wrapper.
#
###
module Exploit

	include Module

	#
	# Wraps the exploitation process in a simple single method.  The options
	# hash can have the following values passed in it:
	#
	# Encoder
	#
	# 	The encoder module that should be used.
	#
	# Payload
	#
	# 	The payload module name that should be used.
	#
	# Target
	#
	# 	The selected target index.
	#
	# Nop
	#
	# 	The NOP generator that should be used in preference.
	#
	# OptionStr
	#
	# 	A string of comma separated option values that should be imported into
	# 	the datastore.
	#
	# Options
	#
	# 	A hash of values to be imported directly into the datastore.
	#
	# LocalInput
	#
	# 	The local input handle that data can be read in from.
	#
	# LocalOutput
	#
	# 	The local output through which data can be displayed.
	#
	# RunAsJob
	#
	# 	Whether or not the exploit should be run in the context of a background
	# 	job.
	#
	def self.exploit_simple(exploit, opts)

		# Import options from the OptionStr or Option hash.
		exploit._import_extra_options(opts)
		
		# Make sure parameters are valid.
		if (opts['Payload'] == nil)
			raise MissingPayloadError, 
				"You must specify a payload.", caller
		end

		# Start it up
		driver = ExploitDriver.new(exploit.framework)

		# Initialize the driver instance
		driver.exploit    = exploit
		driver.payload    = exploit.framework.modules.create(opts['Payload'])

		# Set the force wait for session flag if the caller requested force
		# blocking.  This is so that passive exploits can be blocked on from
		# things like the cli.
		driver.force_wait_for_session = true if (opts['ForceBlocking'] == true)

		# Was the payload valid?
		if (driver.payload == nil)
			raise MissingPayloadError,
				"You specified an invalid payload: #{opts['Payload']}", caller
		end

		# Use the supplied encoder, if any.  If one was not specified, then
		# nil will be assigned causing the exploit to default to picking the
		# best encoder.
		exploit.datastore['ENCODER'] = opts['Encoder']

		# Force the payload to share the exploit's datastore
		driver.payload.share_datastore(driver.exploit.datastore)

		# If we still have no target index, try to use the datastore's index
		target_idx = opts['Target'] || exploit.default_target

		# Convert it to an integer if it's valid
		if (target_idx)
			target_idx = target_idx.to_i
		end

		if (target_idx == nil or target_idx < 0)
			raise MissingTargetError,
				"You must select a target.", caller
		end

		driver.target_idx = target_idx 

		# Set the payload and exploit's subscriber values
		driver.exploit.init_ui(opts['LocalInput'], opts['LocalOutput'])
		driver.payload.init_ui(opts['LocalInput'], opts['LocalOutput'])

		if (opts['RunAsJob'])
			driver.use_job = true
		end

		# Let's rock this party
		session = driver.run

		return session
	end

	#
	# Calls the class method.
	#
	def exploit_simple(opts)
		Msf::Simple::Exploit.exploit_simple(self, opts)
	end

	#
	# Initiates a check, setting up the exploit to be used.  The following
	# options can be specified:
	#
	# LocalInput
	#
	# 	The local input handle that data can be read in from.
	#
	# LocalOutput
	#
	# 	The local output through which data can be displayed.
	#
	def self.check_simple(mod, opts)
		if opts['LocalInput']
			mod.init_ui(opts['LocalInput'], opts['LocalOutput'])
		end

		# Validate the option container state so that options will
		# be normalized
		mod.validate

		# Run check
		mod.check
	end

	#
	# Calls the class method.
	#
	def check_simple(opts)
		Msf::Simple::Exploit.check_simple(self, opts)	
	end

end

end
end
