Add upload/download/delete/mkdir/rmdir to smb session
This commit is contained in:
parent
d964edde11
commit
689caf4bd1
|
@ -81,7 +81,7 @@ PATH
|
|||
rex-zip
|
||||
ruby-macho
|
||||
ruby-mysql
|
||||
ruby_smb (~> 3.3.0)
|
||||
ruby_smb (~> 3.3.3)
|
||||
rubyntlm
|
||||
rubyzip
|
||||
sinatra
|
||||
|
@ -474,8 +474,8 @@ GEM
|
|||
ruby-progressbar (1.13.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby2_keywords (0.0.5)
|
||||
ruby_smb (3.3.2)
|
||||
bindata
|
||||
ruby_smb (3.3.3)
|
||||
bindata (= 2.4.15)
|
||||
openssl-ccm
|
||||
openssl-cmac
|
||||
rubyntlm
|
||||
|
|
|
@ -13,6 +13,8 @@ class Msf::Sessions::SMB
|
|||
attr_accessor :console
|
||||
# @return [RubySMB::Client] The SMB client
|
||||
attr_accessor :client
|
||||
# @return [Rex::Proto::SMB::SimpleClient]
|
||||
attr_accessor :simple_client
|
||||
attr_accessor :platform, :arch
|
||||
attr_reader :framework
|
||||
|
||||
|
@ -21,6 +23,7 @@ class Msf::Sessions::SMB
|
|||
# @option opts [RubySMB::Client] :client
|
||||
def initialize(rstream, opts = {})
|
||||
@client = opts.fetch(:client)
|
||||
@simple_client = ::Rex::Proto::SMB::SimpleClient.new(client.dispatcher.tcp_socket, client: client)
|
||||
self.console = Rex::Post::SMB::Ui::Console.new(self)
|
||||
super(rstream, opts)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rex
|
||||
module Ntpath
|
||||
|
||||
# @param [String] path The path to convert into a valid ntpath format
|
||||
def self.as_ntpath(path)
|
||||
Pathname.new(path)
|
||||
.cleanpath
|
||||
.each_filename
|
||||
.drop_while { |file| file == '.' }
|
||||
.join('\\')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -36,6 +36,7 @@ module Rex
|
|||
# The ruby smb client context
|
||||
self.session = session
|
||||
self.client = session.client
|
||||
self.simple_client = session.simple_client
|
||||
|
||||
# Queued commands array
|
||||
self.commands = []
|
||||
|
@ -125,6 +126,9 @@ module Rex
|
|||
# @return [RubySMB::Client]
|
||||
attr_reader :client # :nodoc:
|
||||
|
||||
# @return [Rex::Proto::SMB::SimpleClient]
|
||||
attr_reader :simple_client
|
||||
|
||||
# @return [RubySMB::SMB2::Tree]
|
||||
attr_accessor :active_share
|
||||
|
||||
|
@ -134,7 +138,7 @@ module Rex
|
|||
def format_prompt(val)
|
||||
if active_share
|
||||
share_name = active_share.share[/[^\\].*$/, 0]
|
||||
cwd = self.cwd.blank? ? '' : "\\#{self.cwd}"
|
||||
cwd = self.cwd.blank? ? '' : "\\#{Rex::Ntpath.as_ntpath(self.cwd)}"
|
||||
prompt = "#{share_name}#{cwd}"
|
||||
else
|
||||
prompt = session.address.to_s
|
||||
|
@ -145,9 +149,8 @@ module Rex
|
|||
|
||||
protected
|
||||
|
||||
attr_writer :session, :client # :nodoc: # :nodoc:
|
||||
attr_writer :session, :client, :simple_client # :nodoc: # :nodoc:
|
||||
attr_accessor :commands # :nodoc:
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -36,6 +36,14 @@ module Rex
|
|||
console.client
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the smb simple client.
|
||||
#
|
||||
# @return [Rex::Proto::SMB::SimpleClient]
|
||||
def simple_client
|
||||
shell.simple_client
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the smb session context.
|
||||
#
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'pathname'
|
||||
require 'rex/post/file'
|
||||
require 'filesize'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
|
@ -16,7 +18,7 @@ module Rex
|
|||
include Rex::Post::SMB::Ui::Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# Initializes an instance of the core command set using the supplied console
|
||||
# Initializes an instance of the shares command set using the supplied console
|
||||
# for interactivity.
|
||||
#
|
||||
# @param [Rex::Post::SMB::Ui::Console] console
|
||||
|
@ -48,6 +50,26 @@ module Rex
|
|||
['-h', '--help'] => [false, 'Help menu' ]
|
||||
)
|
||||
|
||||
@@upload_opts = Rex::Parser::Arguments.new(
|
||||
['-h', '--help'] => [false, 'Help menu' ]
|
||||
)
|
||||
|
||||
@@download_opts = Rex::Parser::Arguments.new(
|
||||
['-h', '--help'] => [false, 'Help menu' ]
|
||||
)
|
||||
|
||||
@@delete_opts = Rex::Parser::Arguments.new(
|
||||
['-h', '--help'] => [false, 'Help menu' ]
|
||||
)
|
||||
|
||||
@@mkdir_opts = Rex::Parser::Arguments.new(
|
||||
['-h', '--help'] => [false, 'Help menu' ]
|
||||
)
|
||||
|
||||
@@rmdir_opts = Rex::Parser::Arguments.new(
|
||||
['-h', '--help'] => [false, 'Help menu' ]
|
||||
)
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
|
@ -58,7 +80,12 @@ module Rex
|
|||
'dir' => 'List all files in the current directory (alias for ls)',
|
||||
'pwd' => 'Print the current remote working directory',
|
||||
'cd' => 'Change the current remote working directory',
|
||||
'cat' => 'Read the file at the given path'
|
||||
'cat' => 'Read the file at the given path',
|
||||
'upload' => 'Upload a file',
|
||||
'download' => 'Download a file',
|
||||
'delete' => 'Delete a file',
|
||||
'mkdir' => 'Make a new directory',
|
||||
'rmdir' => 'Delete a directory'
|
||||
}
|
||||
|
||||
reqs = {}
|
||||
|
@ -157,9 +184,24 @@ module Rex
|
|||
|
||||
return print_no_share_selected unless active_share
|
||||
|
||||
files = active_share.list(directory: as_ntpath(shell.cwd))
|
||||
remote_path = ''
|
||||
|
||||
@@delete_opts.parse(args) do |_opt, idx, val|
|
||||
case idx
|
||||
when 0
|
||||
remote_path = val
|
||||
else
|
||||
print_warning('Too many parameters')
|
||||
cmd_ls_help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
full_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(remote_path).to_s)
|
||||
|
||||
files = active_share.list(directory: full_path)
|
||||
table = Rex::Text::Table.new(
|
||||
'Header' => 'Shares',
|
||||
'Header' => "ls #{full_path}",
|
||||
'Indent' => 4,
|
||||
'Columns' => [ '#', 'Type', 'Name', 'Created', 'Accessed', 'Written', 'Changed', 'Size'],
|
||||
'Rows' => files.map.with_index do |file, i|
|
||||
|
@ -255,12 +297,11 @@ module Rex
|
|||
return print_no_share_selected unless active_share
|
||||
|
||||
path = args[0]
|
||||
# TODO: Needs better normalization
|
||||
new_path = as_ntpath(Pathname.new(shell.cwd).join(path).to_s)
|
||||
native_path = Pathname.new(shell.cwd).join(path).to_s
|
||||
new_path = Rex::Ntpath.as_ntpath(native_path)
|
||||
begin
|
||||
response = active_share.open_directory(directory: new_path)
|
||||
directory = RubySMB::SMB2::File.new(name: new_path, tree: active_share, response: response, encrypt: @tree_connect_encrypt_data)
|
||||
directory.close
|
||||
rescue RubySMB::Error::UnexpectedStatusCode => e
|
||||
# Special case this error to provide better feedback to the user
|
||||
# since I think trying to `cd` to a non-existent directory is pretty likely to accidentally happen
|
||||
|
@ -274,9 +315,11 @@ module Rex
|
|||
print_error('Unknown error occurred while trying to change directory')
|
||||
elog(e)
|
||||
return
|
||||
ensure
|
||||
directory.close if directory
|
||||
end
|
||||
|
||||
shell.cwd = new_path
|
||||
shell.cwd = native_path
|
||||
end
|
||||
|
||||
def cmd_cat_help
|
||||
|
@ -295,14 +338,14 @@ module Rex
|
|||
return
|
||||
end
|
||||
|
||||
return print_no_share_selected if !active_share
|
||||
return print_no_share_selected unless active_share
|
||||
|
||||
path = args[0]
|
||||
|
||||
new_path = as_ntpath(Pathname.new(shell.cwd).join(path).to_s)
|
||||
new_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(path).to_s)
|
||||
|
||||
begin
|
||||
file = active_share.open_file(filename: new_path)
|
||||
file = simple_client.open(new_path, 'o')
|
||||
result = file.read
|
||||
print_line(result)
|
||||
rescue StandardError => e
|
||||
|
@ -320,7 +363,209 @@ module Rex
|
|||
def cmd_cd_tabs(_str, words)
|
||||
return [] if words.length > 1
|
||||
|
||||
@@cat_opts.option_keys
|
||||
@@cd_opts.option_keys
|
||||
end
|
||||
|
||||
def cmd_upload(*args)
|
||||
if args.include?('-h') || args.include?('--help')
|
||||
cmd_upload_help
|
||||
return
|
||||
end
|
||||
|
||||
return print_no_share_selected unless active_share
|
||||
|
||||
local_path = nil
|
||||
remote_path = nil
|
||||
|
||||
@@upload_opts.parse(args) do |_opt, idx, val|
|
||||
case idx
|
||||
when 0
|
||||
local_path = val
|
||||
when 1
|
||||
remote_path = val
|
||||
else
|
||||
print_warning('Too many parameters')
|
||||
cmd_upload_help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if local_path.blank?
|
||||
print_error('No local path given')
|
||||
return
|
||||
end
|
||||
|
||||
remote_path = Rex::Post::File.basename(local_path) if remote_path.nil?
|
||||
full_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(remote_path).to_s)
|
||||
|
||||
upload_file(full_path, local_path)
|
||||
|
||||
print_good("#{local_path} uploaded to #{full_path}")
|
||||
end
|
||||
|
||||
def cmd_upload_tabs(str, words)
|
||||
tab_complete_filenames(str, words)
|
||||
end
|
||||
|
||||
def cmd_upload_help
|
||||
print_line 'Usage: upload <local_path> <remote_path>'
|
||||
print_line
|
||||
print_line 'Upload a file to the remote target.'
|
||||
print @@upload_opts.usage
|
||||
end
|
||||
|
||||
def cmd_download(*args)
|
||||
if args.include?('-h') || args.include?('--help')
|
||||
cmd_download_help
|
||||
return
|
||||
end
|
||||
|
||||
return print_no_share_selected unless active_share
|
||||
|
||||
remote_path = nil
|
||||
local_path = nil
|
||||
|
||||
@@download_opts.parse(args) do |_opt, idx, val|
|
||||
case idx
|
||||
when 0
|
||||
remote_path = val
|
||||
when 1
|
||||
local_path = val
|
||||
else
|
||||
print_warning('Too many parameters')
|
||||
cmd_download_help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if remote_path.blank?
|
||||
print_error('No remote path given')
|
||||
return
|
||||
end
|
||||
|
||||
local_path = Rex::Post::File.basename(remote_path) if local_path.nil?
|
||||
full_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(remote_path).to_s)
|
||||
|
||||
download_file(local_path, full_path)
|
||||
|
||||
print_good("Downloaded #{full_path} to #{local_path}")
|
||||
end
|
||||
|
||||
def cmd_download_help
|
||||
print_line 'Usage: download <remote_path> <local_path>'
|
||||
print_line
|
||||
print_line 'Download a file from the remote target.'
|
||||
print @@download_opts.usage
|
||||
end
|
||||
|
||||
def cmd_delete(*args)
|
||||
if args.include?('-h') || args.include?('--help')
|
||||
cmd_delete_help
|
||||
return
|
||||
end
|
||||
remote_path = nil
|
||||
|
||||
@@delete_opts.parse(args) do |_opt, idx, val|
|
||||
case idx
|
||||
when 0
|
||||
remote_path = val
|
||||
else
|
||||
print_warning('Too many parameters')
|
||||
cmd_delete_help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
full_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(remote_path).to_s)
|
||||
fd = simple_client.open(full_path, 'o')
|
||||
fd.delete
|
||||
print_good("Deleted #{full_path}")
|
||||
end
|
||||
|
||||
def cmd_delete_help
|
||||
print_line 'Usage: delete <remote_path>'
|
||||
print_line
|
||||
print_line 'Delete a file from the remote target.'
|
||||
print @@delete_opts.usage
|
||||
end
|
||||
|
||||
def cmd_mkdir(*args)
|
||||
if args.include?('-h') || args.include?('--help')
|
||||
cmd_mkdir_help
|
||||
return
|
||||
end
|
||||
|
||||
return print_no_share_selected unless active_share
|
||||
|
||||
remote_path = nil
|
||||
|
||||
@@mkdir_opts.parse(args) do |_opt, idx, val|
|
||||
case idx
|
||||
when 0
|
||||
remote_path = val
|
||||
else
|
||||
print_warning('Too many parameters')
|
||||
cmd_mkdir_help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
full_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(remote_path).to_s)
|
||||
|
||||
response = active_share.open_directory(directory: full_path, disposition: RubySMB::Dispositions::FILE_CREATE)
|
||||
directory = RubySMB::SMB2::File.new(name: full_path, tree: active_share, response: response, encrypt: @tree_connect_encrypt_data)
|
||||
print_good("Directory #{full_path} created")
|
||||
ensure
|
||||
directory.close if directory
|
||||
end
|
||||
|
||||
def cmd_mkdir_help
|
||||
print_line 'Usage: mkdir <remote_path>'
|
||||
print_line
|
||||
print_line 'Create a directory on the remote target.'
|
||||
print @@mkdir_opts.usage
|
||||
end
|
||||
|
||||
def cmd_rmdir(*args)
|
||||
if args.include?('-h') || args.include?('--help')
|
||||
cmd_rmdir_help
|
||||
return
|
||||
end
|
||||
|
||||
return print_no_share_selected unless active_share
|
||||
|
||||
remote_path = nil
|
||||
|
||||
@@rmdir_opts.parse(args) do |_opt, idx, val|
|
||||
case idx
|
||||
when 0
|
||||
remote_path = val
|
||||
else
|
||||
print_warning('Too many parameters')
|
||||
cmd_rmdir_help
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
full_path = Rex::Ntpath.as_ntpath(Pathname.new(shell.cwd).join(remote_path).to_s)
|
||||
|
||||
response = active_share.open_directory(directory: full_path, write: true, delete: true, desired_delete: true)
|
||||
directory = RubySMB::SMB2::File.new(name: full_path, tree: active_share, response: response, encrypt: @tree_connect_encrypt_data)
|
||||
status = directory.delete
|
||||
if status == WindowsError::NTStatus::STATUS_SUCCESS
|
||||
print_good("Deleted #{full_path}")
|
||||
else
|
||||
print_error("Error deleting #{full_path}: #{status.name}, #{status.description}")
|
||||
end
|
||||
ensure
|
||||
directory.close if directory
|
||||
end
|
||||
|
||||
def cmd_rmdir_help
|
||||
print_line 'Usage: rmdir <remote_path>'
|
||||
print_line
|
||||
print_line 'Delete a directory from the remote target.'
|
||||
print @@rmdir_opts.usage
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -330,12 +575,56 @@ module Rex
|
|||
nil
|
||||
end
|
||||
|
||||
def as_ntpath(path)
|
||||
Pathname.new(path)
|
||||
.cleanpath
|
||||
.each_filename
|
||||
.drop_while { |file| file == '.' || file == '..' }
|
||||
.join('\\')
|
||||
# Upload a local file to the target
|
||||
# @param dest_file [String] The path for the destination file
|
||||
# @param src_file [String] The path for the source file
|
||||
def upload_file(dest_file, src_file)
|
||||
buf_size = 8 * 1024 * 1024
|
||||
begin
|
||||
dest_fd = simple_client.open(dest_file, 'wct', write: true)
|
||||
src_fd = ::File.open(src_file, "rb")
|
||||
src_size = src_fd.stat.size
|
||||
offset = 0
|
||||
while (buf = src_fd.read(buf_size))
|
||||
offset = dest_fd.write(buf, offset)
|
||||
percent = offset / src_size.to_f * 100.0
|
||||
msg = "Uploaded #{Filesize.new(offset).pretty} of " \
|
||||
"#{Filesize.new(src_size).pretty} (#{percent.round(2)}%)"
|
||||
print_status(msg)
|
||||
end
|
||||
ensure
|
||||
src_fd.close unless src_fd.nil?
|
||||
dest_fd.close unless dest_fd.nil?
|
||||
end
|
||||
end
|
||||
|
||||
# Download a remote file from the target
|
||||
# @param dest_file [String] The path for the destination file
|
||||
# @param src_file [String] The path for the source file
|
||||
def download_file(dest_file, src_file)
|
||||
buf_size = 8 * 1024 * 1024
|
||||
src_fd = simple_client.open(src_file, 'o')
|
||||
# Make the destination path if necessary
|
||||
dir = ::File.dirname(dest_file)
|
||||
::FileUtils.mkdir_p(dir) if dir && !::File.directory?(dir)
|
||||
dst_fd = ::File.new(dest_file, "wb")
|
||||
|
||||
offset = 0
|
||||
src_size = client.open_files[src_fd.file_id].size
|
||||
begin
|
||||
while offset < src_size
|
||||
data = src_fd.read(buf_size, offset)
|
||||
dst_fd.write(data)
|
||||
offset += data.length
|
||||
percent = offset / src_size.to_f * 100.0
|
||||
msg = "Downloaded #{Filesize.new(offset).pretty} of " \
|
||||
"#{Filesize.new(src_size).pretty} (#{percent.round(2)}%)"
|
||||
print_status(msg)
|
||||
end
|
||||
ensure
|
||||
src_fd.close unless src_fd.nil?
|
||||
dst_fd.close unless dst_fd.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -214,6 +214,7 @@ class SimpleClient
|
|||
end
|
||||
|
||||
file_id = self.client.open(path, mode, read: true, write: write || perm.include?('w'))
|
||||
|
||||
else
|
||||
mode = UTILS.open_mode_to_mode(perm)
|
||||
access = UTILS.open_mode_to_access(perm)
|
||||
|
|
|
@ -30,35 +30,36 @@ module Rex::Proto::SMB
|
|||
end
|
||||
|
||||
def read_ruby_smb(length, offset, depth = 0)
|
||||
file_size = client.open_files[client.last_file_id].size
|
||||
file_size_remaining = file_size - offset
|
||||
if length.nil?
|
||||
max_size = client.open_files[client.last_file_id].size
|
||||
fptr = offset
|
||||
|
||||
chunk = [max_size, chunk_size].min
|
||||
|
||||
data = client.read(file_id, fptr, chunk).pack('C*')
|
||||
fptr = data.length
|
||||
|
||||
while data.length < max_size
|
||||
if (max_size - data.length) < chunk
|
||||
chunk = max_size - data.length
|
||||
end
|
||||
data << client.read(file_id, fptr, chunk).pack('C*')
|
||||
fptr = data.length
|
||||
end
|
||||
max_size = file_size_remaining
|
||||
else
|
||||
begin
|
||||
data = client.read(file_id, offset, length).pack('C*')
|
||||
rescue RubySMB::Error::UnexpectedStatusCode => e
|
||||
if e.message == 'STATUS_PIPE_EMPTY' && depth < 20
|
||||
data = read_ruby_smb(length, offset, depth + 1)
|
||||
else
|
||||
raise e
|
||||
end
|
||||
max_size = [length, file_size_remaining].min
|
||||
end
|
||||
|
||||
fptr = offset
|
||||
chunk = [max_size, chunk_size].min
|
||||
|
||||
data = client.read(file_id, fptr, chunk).pack('C*')
|
||||
fptr += data.length
|
||||
|
||||
while data.length < max_size
|
||||
if (max_size - data.length) < chunk
|
||||
chunk = max_size - data.length
|
||||
end
|
||||
new_data = client.read(file_id, fptr, chunk).pack('C*')
|
||||
data << new_data
|
||||
fptr += new_data.length
|
||||
end
|
||||
|
||||
data
|
||||
rescue RubySMB::Error::UnexpectedStatusCode => e
|
||||
if e.message == 'STATUS_PIPE_EMPTY' && depth < 20
|
||||
read_ruby_smb(max_size, offset, depth + 1)
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
def read_rex_smb(length, offset)
|
||||
|
@ -139,6 +140,7 @@ module Rex::Proto::SMB
|
|||
fptr += cl
|
||||
chunk = data.slice!(0, chunk_size)
|
||||
end
|
||||
fptr
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,6 +21,36 @@ class OpenPipe < OpenFile
|
|||
@buff.slice!(0, length)
|
||||
end
|
||||
|
||||
def read_ruby_smb(length, offset, depth = 0)
|
||||
if length.nil?
|
||||
max_size = client.open_files[client.last_file_id].size
|
||||
fptr = offset
|
||||
|
||||
chunk = [max_size, chunk_size].min
|
||||
|
||||
data = client.read(file_id, fptr, chunk).pack('C*')
|
||||
fptr = data.length
|
||||
|
||||
while data.length < max_size
|
||||
if (max_size - data.length) < chunk
|
||||
chunk = max_size - data.length
|
||||
end
|
||||
data << client.read(file_id, fptr, chunk).pack('C*')
|
||||
fptr = data.length
|
||||
end
|
||||
else
|
||||
begin
|
||||
client.read(file_id, offset, length).pack('C*')
|
||||
rescue RubySMB::Error::UnexpectedStatusCode => e
|
||||
if e.message == 'STATUS_PIPE_EMPTY' && depth < 20
|
||||
read_ruby_smb(length, offset, depth + 1)
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def read(length = nil, offset = 0)
|
||||
case self.mode
|
||||
when 'trans'
|
||||
|
|
|
@ -147,7 +147,7 @@ Gem::Specification.new do |spec|
|
|||
spec.add_runtime_dependency 'net-ssh'
|
||||
spec.add_runtime_dependency 'ed25519' # Adds ed25519 keys for net-ssh
|
||||
spec.add_runtime_dependency 'bcrypt_pbkdf'
|
||||
spec.add_runtime_dependency 'ruby_smb', '~> 3.3.0'
|
||||
spec.add_runtime_dependency 'ruby_smb', '~> 3.3.3'
|
||||
spec.add_runtime_dependency 'net-imap' # Used in Postgres auth for its SASL stringprep implementation
|
||||
spec.add_runtime_dependency 'net-ldap'
|
||||
spec.add_runtime_dependency 'net-smtp'
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rspec'
|
||||
|
||||
RSpec.describe Rex::Ntpath do
|
||||
|
||||
describe '#as_ntpath' do
|
||||
let(:valid_windows_path) { 'some\\path\\that\\is\\valid' }
|
||||
|
||||
[
|
||||
'some\\path\\that\\is\\valid',
|
||||
'some/path/that/is/valid',
|
||||
'some/./path/that/./is/valid',
|
||||
'some/extra/../path/that/extra/../is/valid',
|
||||
'/some/path/that/is/valid'
|
||||
].each do |path|
|
||||
context "when the path is #{path}" do
|
||||
it 'formats it as a valid ntpath' do
|
||||
formatted_path = described_class.as_ntpath(path)
|
||||
expect(formatted_path).to eq valid_windows_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,7 +4,10 @@ require 'spec_helper'
|
|||
require 'rex/post/smb/ui/console/command_dispatcher/core'
|
||||
|
||||
RSpec.describe Rex::Post::SMB::Ui::Console::CommandDispatcher::Core do
|
||||
let(:client) { instance_double(RubySMB::Client) }
|
||||
let(:client) { instance_double(RubySMB::Client, dispatcher: dispatcher) }
|
||||
let(:simple_client) { instance_double(Rex::Proto::SMB::SimpleClient) }
|
||||
let(:dispatcher) { instance_double(RubySMB::Dispatcher::Socket, tcp_socket: socket) }
|
||||
let(:socket) { instance_double(IO) }
|
||||
let(:session) { Msf::Sessions::SMB.new(nil, { client: client }) }
|
||||
let(:console) do
|
||||
console = Rex::Post::SMB::Ui::Console.new(session)
|
||||
|
@ -13,6 +16,7 @@ RSpec.describe Rex::Post::SMB::Ui::Console::CommandDispatcher::Core do
|
|||
end
|
||||
|
||||
before(:each) do
|
||||
allow(Rex::Proto::SMB::SimpleClient).to receive(:new).and_return(simple_client)
|
||||
allow(session).to receive(:client).and_return(client)
|
||||
allow(session).to receive(:console).and_return(console)
|
||||
allow(session).to receive(:name).and_return('test client name')
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require 'rex/post/smb/ui/console'
|
||||
require 'rex/post/smb/ui/console/command_dispatcher/shares'
|
||||
|
||||
RSpec.describe Rex::Post::SMB::Ui::Console::CommandDispatcher::Shares do
|
||||
let(:client) { instance_double(RubySMB::Client) }
|
||||
let(:session) { Msf::Sessions::SMB.new(nil, { client: client }) }
|
||||
let(:console) do
|
||||
console = Rex::Post::SMB::Ui::Console.new(session)
|
||||
console.disable_output = true
|
||||
console
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
allow(session).to receive(:client).and_return(client)
|
||||
allow(session).to receive(:console).and_return(console)
|
||||
allow(session).to receive(:name).and_return('test client name')
|
||||
allow(session).to receive(:sid).and_return('test client sid')
|
||||
end
|
||||
|
||||
subject(:command_dispatcher) { described_class.new(session.console) }
|
||||
|
||||
describe '#as_ntpath' do
|
||||
let(:valid_windows_path) { 'some\\path\\that\\is\\valid' }
|
||||
|
||||
[
|
||||
'some\\path\\that\\is\\valid',
|
||||
'some/path/that/is/valid',
|
||||
'some/./path/that/./is/valid',
|
||||
'some/extra/../path/that/extra/../is/valid',
|
||||
'/some/path/that/is/valid'
|
||||
].each do |path|
|
||||
context "when the path is #{path}" do
|
||||
it 'formats it as a valid ntpath' do
|
||||
formatted_path = subject.send(:as_ntpath, path)
|
||||
expect(formatted_path).to eq valid_windows_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue