-
Notifications
You must be signed in to change notification settings - Fork 13.9k
/
server.rb
112 lines (95 loc) · 3.19 KB
/
server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
106
107
108
109
110
111
112
# -*- coding: binary -*-
require 'forwardable'
require 'rex/socket'
module Rex
module Proto
module SMB
###
#
# Acts as an SMB server, processing requests and dispatching them to
# registered procs.
#
###
class Server
include Proto
extend Forwardable
def_delegators :@rubysmb_server, :dialects, :guid, :shares, :add_share, :remove_share
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
# @return [String]
def inspect
"#<#{self.class} smb://#{listen_host}:#{listen_port} >"
end
#
# Returns the hardcore alias for the SMB service
#
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
def alias
super || "SMB Server"
end
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|
Rex::ThreadFactory.spawn("SMBServerClient(#{server_client.peerhost}->#{server_client.dispatcher.tcp_socket.localhost})", false, &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
def stop
self.listener.close
end
def wait
@listener_thread.join if @listener_thread
end
attr_accessor :context, :comm, :listener, :listen_host, :listen_port, :on_client_connect_proc
end
end
end
end