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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a50e0a519bdbc0ab8cccb0116250c2b073e5e305a906d9f46fac5012dc11814
4
- data.tar.gz: 71ac3f8493eae53b548a0e58a207e38034615af0f0d915956d50ab338b5bc16e
3
+ metadata.gz: 9fc6edc1f7ee1557e9bb47fa9af736415cfa7c43fbe9a0869a81cc63f738d7ab
4
+ data.tar.gz: 7664aaf2c58023cbe3f7e5eb3d486a6340ce650def28ca32a311024611bdece5
5
5
  SHA512:
6
- metadata.gz: 5e14f217b9d83deceae6bd11a17d94ce17ca59800850031a0d57d416fe5f1f1431a0de3b8c9d9e8a3f4b4695f9d4e16b15fa2e2cbb808cf16ba409ad60dc67d3
7
- data.tar.gz: ba2eb773c39c1dccfd4b71dbe2b184f453b17cf02690124d010d30d18d3456e4976a7d33f5b11bacda7c192882d1336b686f859ca0147a736ac0a9ff8191ede4
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
- "--authentication-file #{options[:authfile]}"
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]} smbclient \"//#{options[:host]}/#{options[:share]}\" #{password}"
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("#{command} #{option_flags(options)}")
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('') =~ /NT_STATUS_OBJECT_NAME_NOT_FOUND/
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 = @output.expect(/^smb:.*\\>/,@timeout)[0] rescue nil
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 << "--workgroup \"#{options[:domain]}\"" if options[:domain] && !options[:authfile]
309
- flags << "--user \"#{options[:user]}\"" if options[:user] && !options[:authfile]
310
- flags << "--ip-address #{options[:ip_address]}" if options[:ip_address]
311
- flags << "--send-buffer #{options[:buffer_size]}" if options[:buffer_size]
312
- flags << "--debuglevel #{options[:debug_level]}" if options[:debug_level]
313
- flags << '--encrypt' if options[:encrypt]
314
- flags << "--max-protocol #{options[:max_protocol]}" if options[:max_protocol]
315
- flags << '--use-ccache' if options[:use_ccache]
316
- flags << "--socket-options #{options[:socket_options]}" if options[:socket_options]
317
- flags << "--port #{options[:port]}" if options[:port]
318
- flags << "--name-resolve #{options[:name_resolve]}" if options[:name_resolve]
319
- flags << (options[:configfile] ? "--configfile #{options[:configfile]}" : '--configfile /dev/null')
320
- flags.join(' ')
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
@@ -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 -S -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`
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 -S -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"
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
@@ -1,5 +1,5 @@
1
1
  # coding: UTF-8
2
2
 
3
3
  module Sambal
4
- VERSION = "0.2.2"
4
+ VERSION = "0.2.3"
5
5
  end
@@ -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.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: 2018-09-22 00:00:00.000000000 Z
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
- rubyforge_project:
71
- rubygems_version: 2.7.7
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
@@ -1,19 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- spec/sambashare
16
- spec/smb.conf
17
- test/tmp
18
- test/version_tmp
19
- tmp
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in sambal.gemspec
4
- gemspec
5
-
6
- gem 'rspec_junit_formatter', '0.2.2'
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
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
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
@@ -1,6 +0,0 @@
1
- with import <nixpkgs> {};
2
-
3
- stdenv.mkDerivation {
4
- name = "sambal";
5
- buildInputs = [ ruby rake samba ];
6
- }
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