# -*- coding: binary -*-

#
# This mixin implements the pipe_auditor module's primary functionality
#

module Msf
module Exploit::Remote::SMB::Client::PipeAuditor

  include Msf::Exploit::Remote::SMB::Client

  def initialize(info = {})
    super

    named_pipes = File.join(Msf::Config.data_directory, 'wordlists', 'named_pipes.txt')

    register_options([
      OptPath.new('NAMED_PIPES', [true, 'List of named pipes to check', named_pipes])
    ])
  end

  # Check named pipes, returning the first optionally
  #
  # @param check_first [Array] Check the specified pipes first
  # @param return_first [Boolean] Return the first pipe name and handle
  # @return [Array] The list of found pipes (name and handle)
  def check_named_pipes(check_first: [], return_first: false)
    @found_pipes = []

    if check_first.is_a?(Array)
      check_first.delete_if { |pipe| pipe.blank? }
    elsif check_first.is_a?(String) && check_first.present?
      check_first = [check_first]
    else
      check_first = []
    end

    named_pipes = check_first + File.readlines(datastore['NAMED_PIPES'])

    named_pipes.each do |pipe|
      begin
        pipe_name = pipe.strip

        # Samba 3.x requires a prefixed backslash
        # Samba 4.x normalizes away backslashes
        # Windows: honey badger don't care
        unless pipe_name.start_with?('\\')
          pipe_name = "\\#{pipe_name}"
        end

        pipe_handle = self.simple.create_pipe(pipe_name, 'o')

        # If we make it this far, it succeeded
        vprint_status("Connected to named pipe: #{pipe_name}")

        # This is for exploits like ms17_010_psexec
        return pipe_name, pipe_handle if return_first

        @found_pipes << [pipe_name, pipe_handle]
      rescue Rex::Proto::SMB::Exceptions::ErrorCode, RubySMB::Error::RubySMBError => e
        vprint_error("Inaccessible named pipe: #{pipe_name} - #{e.message}")
      end
    end

    @found_pipes
  end

end
end
