Class: Rex::Proto::SMB::Server

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Rex::Proto
Defined in:
lib/rex/proto/smb/server.rb

Overview

Acts as an SMB server, processing requests and dispatching them to registered procs.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port = 445, listen_host = '0.0.0.0', context = {}, comm = nil, gss_provider: nil, logger: nil) ⇒ Server

Returns a new instance of Server.



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/rex/proto/smb/server.rb', line 23

def initialize(port = 445, listen_host = '0.0.0.0', context = {}, comm = nil, gss_provider: nil, logger: nil)
  self.listen_host     = listen_host
  self.listen_port     = port
  self.context         = context
  self.comm            = comm
  @gss_provider        = gss_provider
  @logger              = logger
  self.listener        = nil
  @listener_thread     = nil
  @rubysmb_server      = nil
end

Instance Attribute Details

#commObject

Returns the value of attribute comm.



115
116
117
# File 'lib/rex/proto/smb/server.rb', line 115

def comm
  @comm
end

#contextObject

Returns the value of attribute context.



115
116
117
# File 'lib/rex/proto/smb/server.rb', line 115

def context
  @context
end

#listen_hostObject

Returns the value of attribute listen_host.



115
116
117
# File 'lib/rex/proto/smb/server.rb', line 115

def listen_host
  @listen_host
end

#listen_portObject

Returns the value of attribute listen_port.



115
116
117
# File 'lib/rex/proto/smb/server.rb', line 115

def listen_port
  @listen_port
end

#listenerObject

Returns the value of attribute listener.



115
116
117
# File 'lib/rex/proto/smb/server.rb', line 115

def listener
  @listener
end

#on_client_connect_procObject

Returns the value of attribute on_client_connect_proc.



115
116
117
# File 'lib/rex/proto/smb/server.rb', line 115

def on_client_connect_proc
  @on_client_connect_proc
end

Class Method Details

.hardcore_alias(*args, **kwargs) ⇒ Object

Returns the hardcore alias for the SMB service



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rex/proto/smb/server.rb', line 43

def self.hardcore_alias(*args, **kwargs)
  gss_alias = ''
  if (gss_provider = kwargs[:gss_provider])
    gss_alias << "#{gss_provider.class}("
    attrs = {}
    if gss_provider.is_a?(RubySMB::Gss::Provider::NTLM)
      allows = []
      allows << 'ANONYMOUS' if gss_provider.allow_anonymous
      allows << 'GUESTS' if gss_provider.allow_guests
      attrs['allow'] = allows.join('|') unless allows.empty?
      attrs['default_domain'] = gss_provider.default_domain if gss_provider.respond_to?(:default_domain) && gss_provider.default_domain.present?
      attrs['ntlm_status'] = gss_provider.ntlm_type3_status.name if gss_provider.respond_to?(:ntlm_type3_status) && gss_provider.ntlm_type3_status.present?
    end
    gss_alias << attrs.map { |k,v| "#{k}=#{v}"}.join(', ')
    gss_alias << ')'
  end
  "#{(args[0] || '')}-#{(args[1] || '')}-#{args[3] || ''}-#{gss_alias}"
end

Instance Method Details

#aliasObject



62
63
64
# File 'lib/rex/proto/smb/server.rb', line 62

def alias
  super || "SMB Server"
end

#inspectString

Returns:

  • (String)


36
37
38
# File 'lib/rex/proto/smb/server.rb', line 36

def inspect
  "#<#{self.class} smb://#{listen_host}:#{listen_port} >"
end

#startObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/rex/proto/smb/server.rb', line 66

def start
  self.listener = Rex::Socket::TcpServer.create(
    'LocalHost'      => self.listen_host,
    'LocalPort'      => self.listen_port,
    'Context'        => self.context,
    'Comm'           => self.comm
  )

  thread_factory = Proc.new do |server_client, &block|
    thread_name = "SMBServerClient(#{server_client.peerhost}->#{server_client.dispatcher.tcp_socket.localhost})"
    wrapped_block = Proc.new do
      begin
        block.call
      rescue StandardError => e
        elog(thread_name, error: e)
      end
    end

    Rex::ThreadFactory.spawn(thread_name, false, &wrapped_block)
  end
  @rubysmb_server = RubySMB::Server.new(
    server_sock: self.listener,
    gss_provider: @gss_provider,
    logger: @logger,
    thread_factory: thread_factory
  )

  localinfo = Rex::Socket.to_authority(self.listener.localhost, self.listener.localport)
  @listener_thread = Rex::ThreadFactory.spawn("SMBServerListener(#{localinfo})", false) do
    begin
      @rubysmb_server.run do |server_client|
        on_client_connect_proc.call(server_client) if on_client_connect_proc
        true
      end
    rescue IOError => e
      # this 'IOError: stream closed in another thread' is expected, so disregard it
      wlog("#{e.class}: #{e.message}")
    end
  end
end

#stopObject



107
108
109
# File 'lib/rex/proto/smb/server.rb', line 107

def stop
  self.listener.close
end

#waitObject



111
112
113
# File 'lib/rex/proto/smb/server.rb', line 111

def wait
  @listener_thread.join if @listener_thread
end