Class: RubySMB::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_smb/server.rb,
lib/ruby_smb/server/cli.rb,
lib/ruby_smb/server/share.rb,
lib/ruby_smb/server/session.rb,
lib/ruby_smb/server/server_client.rb,
lib/ruby_smb/server/share/provider.rb,
lib/ruby_smb/server/share/provider/disk.rb,
lib/ruby_smb/server/share/provider/pipe.rb,
lib/ruby_smb/server/server_client/share_io.rb,
lib/ruby_smb/server/server_client/encryption.rb,
lib/ruby_smb/server/share/provider/processor.rb,
lib/ruby_smb/server/server_client/negotiation.rb,
lib/ruby_smb/server/server_client/tree_connect.rb,
lib/ruby_smb/server/server_client/session_setup.rb,
lib/ruby_smb/server/share/provider/virtual_disk.rb,
lib/ruby_smb/server/share/provider/disk/processor.rb,
lib/ruby_smb/server/share/provider/disk/file_system.rb,
lib/ruby_smb/server/share/provider/disk/processor/read.rb,
lib/ruby_smb/server/share/provider/disk/processor/close.rb,
lib/ruby_smb/server/share/provider/disk/processor/query.rb,
lib/ruby_smb/server/share/provider/disk/processor/create.rb,
lib/ruby_smb/server/share/provider/virtual_disk/virtual_file.rb,
lib/ruby_smb/server/share/provider/virtual_disk/virtual_stat.rb,
lib/ruby_smb/server/share/provider/virtual_disk/virtual_pathname.rb

Overview

This class provides the SMB server core. Settings that are relevant server wide are managed by this object. Currently, the server only supports negotiating and authenticating requests. No other server functionality is available at this time. The negotiating and authentication is supported for SMB versions 1 through 3.1.1.

Defined Under Namespace

Modules: Cli, Share Classes: Connection, ServerClient, Session

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server_sock: nil, gss_provider: nil, logger: nil, thread_factory: nil) ⇒ Server

Returns a new instance of Server.

Parameters:

  • server_sock (defaults to: nil)

    the socket on which the server should listen

  • gss_provider (Gss::Provider) (defaults to: nil)

    the authentication provider

  • logger (::Logger) (defaults to: nil)

    the logger to use for diagnostic messages

  • thread_factory (defaults to: nil)

    a block to create threads for serving clients



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
# File 'lib/ruby_smb/server.rb', line 21

def initialize(server_sock: nil, gss_provider: nil, logger: nil, thread_factory: nil)
  server_sock = ::TCPServer.new(445) if server_sock.nil?

  @guid = Random.new.bytes(16)
  @socket = server_sock
  @connections = []
  @gss_provider = gss_provider || Gss::Provider::NTLM.new
  # reject the wildcard dialect because it's not a real dialect we can use for this purpose
  @dialects = RubySMB::Dialect::ALL.keys.reject { |dialect| dialect == "0x%04x" % RubySMB::SMB2::SMB2_WILDCARD_REVISION }.reverse

  case logger
  when nil
    @logger = Logger.new(File.open(File::NULL, 'w'))
  when :stdout
    @logger = Logger.new(STDOUT)
  when :stderr
    @logger = Logger.new(STDERR)
  else
    @logger = logger
  end

  if thread_factory.nil?
    # the default thread factory uses Ruby's standard Thread#new
    thread_factory = Proc.new do |_server_client, &block|
      Thread.new(&block)
    end
  end
  @thread_factory = thread_factory

  # share name => provider instance
  @shares = {
    'IPC$' => Share::Provider::IpcPipe.new
  }
end

Instance Attribute Details

#dialectsArray<String>

Returns:

  • (Array<String>)


86
87
88
# File 'lib/ruby_smb/server.rb', line 86

def dialects
  @dialects
end

#gss_providerObject (readonly)

The GSS Provider instance that this server will use to authenticate incoming client connections.



92
93
94
# File 'lib/ruby_smb/server.rb', line 92

def gss_provider
  @gss_provider
end

#guidObject (readonly)

The 16 byte GUID that uniquely identifies this server instance.



96
97
98
# File 'lib/ruby_smb/server.rb', line 96

def guid
  @guid
end

#loggerObject (readonly)

The logger instance to use for diagnostic messages.



100
101
102
# File 'lib/ruby_smb/server.rb', line 100

def logger
  @logger
end

#sharesObject (readonly)

The shares that are provided by this server



104
105
106
# File 'lib/ruby_smb/server.rb', line 104

def shares
  @shares
end

Instance Method Details

#add_share(share_provider) ⇒ Object

Parameters:



57
58
59
60
# File 'lib/ruby_smb/server.rb', line 57

def add_share(share_provider)
  logger.debug("Adding #{share_provider.type} share: #{share_provider.name}")
  @shares[share_provider.name] = share_provider
end

#remove_share(share_provider) ⇒ Object

Parameters:



63
64
65
66
67
68
69
# File 'lib/ruby_smb/server.rb', line 63

def remove_share(share_provider)
  share_provider = share_provider.name if share_provider.is_a?(RubySMB::Server::Share::Provider::Base)
  logger.debug("Removing share: #{share_provider}")
  @shares.delete(share_provider)

  nil
end

#run(&block) ⇒ Object

Run the server and accept any connections. For each connection, the block will be executed if specified. When the block returns false, the loop will exit and the server will no long accept new connections.



73
74
75
76
77
78
79
80
81
# File 'lib/ruby_smb/server.rb', line 73

def run(&block)
  loop do
    sock = @socket.accept
    server_client = ServerClient.new(self, RubySMB::Dispatcher::Socket.new(sock, read_timeout: nil))
    @connections << Connection.new(server_client, @thread_factory.call(server_client) { server_client.run })

    break unless block.nil? || block.call(server_client)
  end
end