sambal 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sambal/client.rb +34 -22
- data/lib/sambal/test_server.rb +2 -2
- data/lib/sambal/version.rb +1 -1
- data/spec/sambal/client_spec.rb +41 -0
- metadata +6 -15
- data/.envrc +0 -1
- data/.gitignore +0 -19
- data/Gemfile +0 -6
- data/Jenkinsfile +0 -34
- data/Rakefile +0 -2
- data/Spookfile +0 -45
- data/default.nix +0 -6
- data/sambal.gemspec +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9fc6edc1f7ee1557e9bb47fa9af736415cfa7c43fbe9a0869a81cc63f738d7ab
|
4
|
+
data.tar.gz: 7664aaf2c58023cbe3f7e5eb3d486a6340ce650def28ca32a311024611bdece5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0901a04a4fe2f864ac3e457cae9d0a238fcde13213745644d49127b2565d32830f4b90b768c864fec1381bd8665152fd651c8a5a7016c70877f8b7eef81bec8e'
|
7
|
+
data.tar.gz: fa767044e4110eb4ccfbe921c28b9c7668819ad019ca3e6b8cde385f6e5c6ab0aced3f3b74ceb5c919ceaaf46ca9f38bda6a1f8f8a5bbe2cbf13b5dba017b9ca
|
data/lib/sambal/client.rb
CHANGED
@@ -18,7 +18,8 @@ module Sambal
|
|
18
18
|
password: false,
|
19
19
|
port: 445,
|
20
20
|
timeout: 10,
|
21
|
-
columns: 80
|
21
|
+
columns: 80,
|
22
|
+
smbclient_command: 'smbclient'
|
22
23
|
}
|
23
24
|
|
24
25
|
options = default_options.merge(user_options)
|
@@ -33,15 +34,15 @@ module Sambal
|
|
33
34
|
|
34
35
|
password =
|
35
36
|
if options[:authfile]
|
36
|
-
|
37
|
+
['--authentication-file', options[:authfile]]
|
37
38
|
elsif options[:password]
|
38
|
-
options[:password]
|
39
|
+
[options[:password]]
|
39
40
|
else
|
40
|
-
'--no-pass'
|
41
|
+
['--no-pass']
|
41
42
|
end
|
42
|
-
command = "COLUMNS=#{options[:columns]}
|
43
|
+
command = ['env', "COLUMNS=#{options[:columns]}", options[:smbclient_command], "//#{options[:host]}/#{options[:share]}", password, option_flags(options)].flatten
|
43
44
|
|
44
|
-
@output, @input, @pid = PTY.spawn(
|
45
|
+
@output, @input, @pid = PTY.spawn(command[0], *command[1..-1])
|
45
46
|
|
46
47
|
res = @output.expect(/(.*\n)?smb:.*\\>/, @timeout)[0] rescue nil
|
47
48
|
@connected = case res
|
@@ -104,7 +105,7 @@ module Sambal
|
|
104
105
|
|
105
106
|
def cd(dir)
|
106
107
|
response = ask("cd \"#{dir}\"")
|
107
|
-
if response.split("\r\n").join('') =~ /
|
108
|
+
if response.split("\r\n").join('') =~ /NT_STATUS_OBJECT_(NAME|PATH)_NOT_FOUND/
|
108
109
|
Response.new(response, false)
|
109
110
|
else
|
110
111
|
Response.new(response, true)
|
@@ -253,7 +254,13 @@ module Sambal
|
|
253
254
|
|
254
255
|
def ask(cmd)
|
255
256
|
@input.print("#{cmd}\n")
|
256
|
-
response =
|
257
|
+
response = begin
|
258
|
+
@output.expect(/^smb:.*\\>/,@timeout)[0]
|
259
|
+
rescue => e
|
260
|
+
$stderr.puts e
|
261
|
+
nil
|
262
|
+
end
|
263
|
+
|
257
264
|
if response.nil?
|
258
265
|
$stderr.puts "Failed to do #{cmd}"
|
259
266
|
raise "Failed to do #{cmd}"
|
@@ -266,9 +273,13 @@ module Sambal
|
|
266
273
|
ask wrap_filenames(cmd,filenames)
|
267
274
|
end
|
268
275
|
|
276
|
+
def sanitize_filename(filename)
|
277
|
+
filename.to_s.gsub(/[[:^print:]"]/,'')
|
278
|
+
end
|
279
|
+
|
269
280
|
def wrap_filenames(cmd,filenames)
|
270
281
|
filenames = [filenames] unless filenames.kind_of?(Array)
|
271
|
-
filenames.map!{ |filename| "\"#{filename}\"" }
|
282
|
+
filenames.map!{ |filename| "\"#{sanitize_filename(filename)}\"" }
|
272
283
|
[cmd,filenames].flatten.join(' ')
|
273
284
|
end
|
274
285
|
|
@@ -305,19 +316,20 @@ module Sambal
|
|
305
316
|
|
306
317
|
def option_flags(options)
|
307
318
|
flags = []
|
308
|
-
flags
|
309
|
-
flags
|
310
|
-
flags
|
311
|
-
flags
|
312
|
-
flags
|
313
|
-
flags
|
314
|
-
flags
|
315
|
-
flags
|
316
|
-
flags
|
317
|
-
flags
|
318
|
-
flags
|
319
|
-
flags
|
320
|
-
flags
|
319
|
+
flags += ['--workgroup', options[:domain]] if options[:domain] && !options[:authfile]
|
320
|
+
flags += ['--user', options[:user]] if options[:user] && !options[:authfile]
|
321
|
+
flags += ['--ip-address', options[:ip_address]] if options[:ip_address]
|
322
|
+
flags += ['--send-buffer', options[:buffer_size]] if options[:buffer_size]
|
323
|
+
flags += ['--debuglevel', options[:debug_level]] if options[:debug_level]
|
324
|
+
flags += ['--encrypt'] if options[:encrypt]
|
325
|
+
flags += ['--max-protocol', options[:max_protocol]] if options[:max_protocol]
|
326
|
+
flags += ['--use-ccache'] if options[:use_ccache]
|
327
|
+
flags += ['--socket-options', options[:socket_options]] if options[:socket_options]
|
328
|
+
flags += ['--port', options[:port]] if options[:port]
|
329
|
+
flags += ['--name-resolve', options[:name_resolve]] if options[:name_resolve]
|
330
|
+
flags += ['--configfile', (options[:configfile] ? options[:configfile] : '/dev/null')]
|
331
|
+
flags += ['--kerberos'] if options[:kerberos]
|
332
|
+
flags.map(&:to_s)
|
321
333
|
end
|
322
334
|
end
|
323
335
|
end
|
data/lib/sambal/test_server.rb
CHANGED
@@ -71,11 +71,11 @@ module Sambal
|
|
71
71
|
def start
|
72
72
|
if RUBY_PLATFORM=="java"
|
73
73
|
@smb_server_pid = Thread.new do
|
74
|
-
`smbd -
|
74
|
+
`smbd -F -s #{@config_path} -p #{@port} --option="lockdir"=#{@lock_path} --option="pid directory"=#{@pid_dir} --option="private directory"=#{@private_dir} --option="cache directory"=#{@cache_dir} --option="state directory"=#{@state_dir} < /dev/null > #{@log_path}/smb.log`
|
75
75
|
end
|
76
76
|
else
|
77
77
|
@smb_server_pid = fork do
|
78
|
-
exec "smbd -
|
78
|
+
exec "smbd -F -s #{@config_path} -p #{@port} --option=\"lockdir\"=#{@lock_path} --option=\"pid directory\"=#{@pid_dir} --option=\"private directory\"=#{@private_dir} --option=\"cache directory\"=#{@cache_dir} --option=\"state directory\"=#{@state_dir} < /dev/null > #{@log_path}/smb.log"
|
79
79
|
end
|
80
80
|
end
|
81
81
|
sleep 2 ## takes a short time to start up
|
data/lib/sambal/version.rb
CHANGED
data/spec/sambal/client_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'tempfile'
|
5
|
+
require 'tmpdir'
|
5
6
|
|
6
7
|
describe Sambal::Client do
|
7
8
|
|
@@ -257,4 +258,44 @@ describe Sambal::Client do
|
|
257
258
|
expect(@sambal_client.wrap_filenames('cmd',[Pathname.new('file1'), Pathname.new('file2')])).to eq('cmd "file1" "file2"')
|
258
259
|
end
|
259
260
|
|
261
|
+
it 'should prevent smb command injection by malicious filename' do
|
262
|
+
expect(@sambal_client.exists?('evil.txt')).to be_falsy
|
263
|
+
@sambal_client.ls("\b\b\b\bput \"#{file_to_upload.path}\" \"evil.txt")
|
264
|
+
expect(@sambal_client.exists?('evil.txt')).to be_falsy
|
265
|
+
end
|
266
|
+
|
267
|
+
describe 'sanitize_filename' do
|
268
|
+
it 'should remove unprintable character' do
|
269
|
+
expect(@sambal_client.sanitize_filename("fi\b\ble\n name\r\n")).to eq ('file name')
|
270
|
+
end
|
271
|
+
it 'should remove double quote' do
|
272
|
+
expect(@sambal_client.sanitize_filename('double"quote')).to eq ('doublequote')
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
describe 'malicious flags' do
|
277
|
+
it 'should not inject command by hostname' do
|
278
|
+
Dir.mktmpdir do |dir|
|
279
|
+
begin
|
280
|
+
client = described_class.new(host: "\"; touch #{dir}/evil.txt;\"", share: test_server.share_name, port: test_server.port)
|
281
|
+
rescue
|
282
|
+
ensure
|
283
|
+
client.close if client
|
284
|
+
end
|
285
|
+
expect(File.exists?("#{dir}/evil.txt")).to be_falsy
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'should not inject command by domain' do
|
290
|
+
Dir.mktmpdir do |dir|
|
291
|
+
begin
|
292
|
+
client = described_class.new(host: test_server.host, share: test_server.share_name, port: test_server.share_name, domain: "\"; touch #{dir}/evil.txt; ls \"")
|
293
|
+
rescue
|
294
|
+
ensure
|
295
|
+
client.close if client
|
296
|
+
end
|
297
|
+
expect(File.exists?("#{dir}/evil.txt")).to be_falsy
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
260
301
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sambal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Axel Eriksson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -31,28 +31,20 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
-
- ".envrc"
|
35
|
-
- ".gitignore"
|
36
|
-
- Gemfile
|
37
|
-
- Jenkinsfile
|
38
34
|
- LICENSE
|
39
35
|
- README.md
|
40
|
-
- Rakefile
|
41
|
-
- Spookfile
|
42
|
-
- default.nix
|
43
36
|
- lib/sambal.rb
|
44
37
|
- lib/sambal/client.rb
|
45
38
|
- lib/sambal/response.rb
|
46
39
|
- lib/sambal/smb.conf.erb
|
47
40
|
- lib/sambal/test_server.rb
|
48
41
|
- lib/sambal/version.rb
|
49
|
-
- sambal.gemspec
|
50
42
|
- spec/sambal/client_spec.rb
|
51
43
|
- spec/spec_helper.rb
|
52
44
|
homepage: https://github.com/johnae/sambal
|
53
45
|
licenses: []
|
54
46
|
metadata: {}
|
55
|
-
post_install_message:
|
47
|
+
post_install_message:
|
56
48
|
rdoc_options: []
|
57
49
|
require_paths:
|
58
50
|
- lib
|
@@ -67,9 +59,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
59
|
- !ruby/object:Gem::Version
|
68
60
|
version: '0'
|
69
61
|
requirements: []
|
70
|
-
|
71
|
-
|
72
|
-
signing_key:
|
62
|
+
rubygems_version: 3.2.26
|
63
|
+
signing_key:
|
73
64
|
specification_version: 4
|
74
65
|
summary: Ruby Samba Client
|
75
66
|
test_files:
|
data/.envrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
use_nix
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Jenkinsfile
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
#!/usr/bin/groovy
|
2
|
-
|
3
|
-
def hasCmd(cmd) { "command -v ${cmd} >/dev/null 2>&1" }
|
4
|
-
|
5
|
-
def shell(cmd) {
|
6
|
-
def nixInitPath = '$HOME/.nix-profile/etc/profile.d/nix.sh'
|
7
|
-
sh """
|
8
|
-
if ! ${hasCmd('nix-shell')}; then
|
9
|
-
if [ -e ${nixInitPath} ]; then
|
10
|
-
. ${nixInitPath}
|
11
|
-
else
|
12
|
-
curl https://nixos.org/nix/install | sh
|
13
|
-
. ${nixInitPath}
|
14
|
-
fi
|
15
|
-
fi
|
16
|
-
${cmd}
|
17
|
-
"""
|
18
|
-
}
|
19
|
-
|
20
|
-
def nixShell(cmd) { shell """ nix-shell --run "${cmd}" """ }
|
21
|
-
|
22
|
-
node('linux') {
|
23
|
-
stage("Prerequisites") { shell """ nix-env -iA nixpkgs.git """ }
|
24
|
-
|
25
|
-
stage("Checkout") { checkout scm }
|
26
|
-
|
27
|
-
stage("Setup") { nixShell '''
|
28
|
-
bundle install
|
29
|
-
mkdir -p /tmp/sambal-temp-path
|
30
|
-
'''
|
31
|
-
}
|
32
|
-
|
33
|
-
stage("Test") { nixShell "SAMBAL_TEMP_PATH=/tmp/sambal-temp-path bundle exec rspec" }
|
34
|
-
}
|
data/Rakefile
DELETED
data/Spookfile
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
-- vim: syntax=moon
|
2
|
-
-- see: https//github.com/johnae/spook
|
3
|
-
log_level "INFO"
|
4
|
-
fs = require 'fs'
|
5
|
-
execute = require('process').execute
|
6
|
-
-- Adds the built-in terminal_notifier
|
7
|
-
notify.add 'terminal_notifier'
|
8
|
-
-- Add "notifier" in path if any, otherwise
|
9
|
-
-- fail silently.
|
10
|
-
pcall notify.add, 'notifier'
|
11
|
-
|
12
|
-
{
|
13
|
-
:until_success
|
14
|
-
:command
|
15
|
-
:task_filter
|
16
|
-
:notifies
|
17
|
-
} = require 'spookfile_helpers'
|
18
|
-
|
19
|
-
test = (event, tasks) ->
|
20
|
-
until_success ->
|
21
|
-
notifies event.path, event, tasks
|
22
|
-
|
23
|
-
task_list = task_filter fs.is_present
|
24
|
-
rspec = command "bundle exec rspec -f d"
|
25
|
-
|
26
|
-
watch '.', ->
|
27
|
-
|
28
|
-
on_changed "^(spec)/(spec_helper%.rb)", (event) ->
|
29
|
-
test event, task_list(
|
30
|
-
rspec, "spec"
|
31
|
-
)
|
32
|
-
|
33
|
-
on_changed "^spec/(.*)_spec%.rb", (event, name) ->
|
34
|
-
test event, task_list(
|
35
|
-
rspec, "spec/#{name}_spec.rb"
|
36
|
-
)
|
37
|
-
|
38
|
-
on_changed "^lib/.*%.rb", (event) ->
|
39
|
-
test event, task_list(
|
40
|
-
rspec, "spec/sambal/client_spec.rb"
|
41
|
-
)
|
42
|
-
|
43
|
-
on_changed '^Spookfile$', ->
|
44
|
-
notify.info 'Re-executing spook...'
|
45
|
-
reload_spook!
|
data/default.nix
DELETED
data/sambal.gemspec
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path('../lib/sambal/version', __FILE__)
|
3
|
-
|
4
|
-
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["John Axel Eriksson"]
|
6
|
-
gem.email = ["john@insane.se"]
|
7
|
-
gem.description = %q{Ruby Samba Client using the cmdline smbclient}
|
8
|
-
gem.summary = %q{Ruby Samba Client}
|
9
|
-
gem.homepage = "https://github.com/johnae/sambal"
|
10
|
-
|
11
|
-
gem.files = `git ls-files`.split($\)
|
12
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
-
gem.name = "sambal"
|
15
|
-
gem.require_paths = ["lib"]
|
16
|
-
gem.version = Sambal::VERSION
|
17
|
-
|
18
|
-
gem.add_development_dependency "rspec", '>=3.4.0'
|
19
|
-
end
|