nobspw 0.5.1 → 0.6.0

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: a69bacd3f3f32acf44341c98cc21d7680a46638d6404b62e51ebe1ec09170a26
4
- data.tar.gz: 84cf94ef83bad08505f3563f54fe3f1cebb8b87ef7583f26a47e525b2d6a2baf
3
+ metadata.gz: 061211b1866c17a90bd78bbb371e862c1a977c69ea168a01ac1fbab714fcde23
4
+ data.tar.gz: f9b54a073ac61f81450acb7213ff73f63a1d5835df7f3e9f819f076f0de935d1
5
5
  SHA512:
6
- metadata.gz: a3b89294eb061d12bbce3d2e69554598993c84e61fd54e352a16cbaaf298df86d3755e05ab2acaa52d19525f4580d72db947dacbc34cbb17f3e215a8bd8f560b
7
- data.tar.gz: 9c5d5c21fcf1dbdbbab22081e0cd263d5acd0949dc32216c5d2aae3d60e6aea65f0b16729b29ad4011d49ad7cb9a693c76deb70cbb4cefce7fd897da0774ed6e
6
+ metadata.gz: aa07f2332b6ffe8952be7b28aca35978267a735afc8a72dd35f32fb4135e08fd9593653f90981aea8fef91c6a7c45b07e255058f65488831aa1050534e1aee16
7
+ data.tar.gz: 976fadf800426c97e8824990457283afc32f7027ac1cf627e7fb7be7e132b220d29b859468c917c3cc29be9bfd57188561c40e16e0c5683ec6aaef54d3643193
data/README.md CHANGED
@@ -60,6 +60,7 @@ Optionally, you can configure some options:
60
60
  config.min_unique_characters = 5
61
61
  config.dictionary_path = 'path/to/dictionary.txt'
62
62
  config.grep_path = '/usr/bin/grep'
63
+ config.use_ruby_grep = false # Defaults to false; slower when true. Uses Ruby's internal Grep method instead of shelling out.
63
64
  config.domain_name = 'mywebsitedomain.com' # it is recommended you configure this
64
65
  config.blacklist = ['this_password_is_not_allowed', /password/]
65
66
  end
@@ -5,6 +5,7 @@ module NOBSPW
5
5
  attr_accessor :min_unique_characters
6
6
  attr_accessor :dictionary_path
7
7
  attr_accessor :grep_path
8
+ attr_accessor :use_ruby_grep
8
9
  attr_accessor :domain_name
9
10
  attr_accessor :blacklist
10
11
  attr_accessor :validation_methods
@@ -16,6 +17,7 @@ module NOBSPW
16
17
  @min_unique_characters = 5
17
18
  @dictionary_path = File.join(File.dirname(__FILE__), "..", "db", "dictionary.txt")
18
19
  @grep_path = `which grep`.strip
20
+ @use_ruby_grep = !@grep_path.present?
19
21
  @domain_name = nil
20
22
  @blacklist = nil
21
23
  @validation_methods = NOBSPW::ValidationMethods::DEFAULT_VALIDATION_METHODS
@@ -37,10 +37,5 @@ module NOBSPW
37
37
 
38
38
  @strong = @weak_password_reasons.empty?
39
39
  end
40
-
41
- def grep_command(path)
42
- escaped_pw = Shellwords.escape(@password)
43
- "#{NOBSPW.configuration.grep_path} '^#{escaped_pw}$' #{path}"
44
- end
45
40
  end
46
41
  end
@@ -1,3 +1,6 @@
1
+ require 'shellwords'
2
+ require 'open3'
3
+
1
4
  module NOBSPW
2
5
  module ValidationMethods
3
6
  DEFAULT_VALIDATION_METHODS = %i(password_empty?
@@ -12,6 +15,8 @@ module NOBSPW
12
15
  password_too_common?)
13
16
 
14
17
  INTERRUPT_VALIDATION_FOR = %i(password_empty?)
18
+ STDIN_GREP_COMMAND = ['/usr/bin/grep', '-m 1', '-f', '/dev/stdin',
19
+ NOBSPW.configuration.dictionary_path]
15
20
 
16
21
  private
17
22
 
@@ -81,22 +86,27 @@ module NOBSPW
81
86
  end
82
87
 
83
88
  def password_too_common?
84
- `#{grep_command(NOBSPW.configuration.dictionary_path)}`
85
-
86
- case $?.exitstatus
87
- when 0
88
- true
89
- when 1
90
- false
91
- when 127
92
- raise StandardError.new("Grep not found at: #{NOBSPW.configuration.grep_path}")
93
- else
94
- false
95
- end
89
+ NOBSPW.configuration.use_ruby_grep ? ruby_grep : shell_grep
96
90
  end
97
91
 
98
92
  # Helper methods
99
93
 
94
+ def shell_grep
95
+ raise StandardError.new("Grep not found at: #{NOBSPW.configuration.grep_path}") \
96
+ if !File.exist?(NOBSPW.configuration.grep_path)
97
+
98
+ output = Open3.popen3(STDIN_GREP_COMMAND.join(" "), out: '/dev/null') { |stdin, stdout, stderr, wait_thr|
99
+ stdin.puts "^#{excaped_password}$"
100
+ stdin.close
101
+ wait_thr.value
102
+ }
103
+ output.success?
104
+ end
105
+
106
+ def ruby_grep
107
+ File.open(NOBSPW.configuration.dictionary_path).grep(/^#{escaped_password}$/).present?
108
+ end
109
+
100
110
  def email_without_extension(email)
101
111
  name, domain, whatev = email&.split("@", 3)
102
112
  "#{name}@#{strip_extension_from_domain(domain)}"
@@ -110,5 +120,8 @@ module NOBSPW
110
120
  str&.gsub(/-|_|\.|\'|\"|\@/, ' ')
111
121
  end
112
122
 
123
+ def escaped_password(password = @password)
124
+ Shellwords.escape(password)
125
+ end
113
126
  end
114
127
  end
@@ -1,3 +1,3 @@
1
1
  module NOBSPW
2
- VERSION = '0.5.1'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -2,22 +2,72 @@
2
2
 
3
3
  require 'benchmark'
4
4
  require 'shellwords'
5
+ require 'open3'
6
+ require 'subprocess'
7
+
8
+ ITERATIONS = 100
9
+ DICTIONARY_PATH = File.join(File.dirname(__FILE__), '..', 'lib/db/dictionary.txt')
10
+ STDIN_GREP_COMMAND = ['/usr/bin/grep', '-m 1', '-f', '/dev/stdin', DICTIONARY_PATH]
5
11
 
6
12
  password = 'swordfish'
7
- dictionary_path = File.join(File.dirname(__FILE__), '..', 'lib/db/dictionary.txt')
8
13
 
9
- def shell_grep(password, dictionary)
14
+ def shell_grep(password)
10
15
  password = Shellwords.escape(password)
11
- "/usr/bin/grep '^#{password}$' #{dictionary}"
16
+ `/usr/bin/grep -m 1 '^#{password}$' #{DICTIONARY_PATH}`
12
17
  $?.exitstatus == 0
13
18
  end
14
19
 
15
- Benchmark.bm do |benchmark|
16
- benchmark.report("Ruby") do
17
- 25.times { File.open(dictionary_path).grep(/^#{password}$/) }
20
+ def shell_grep_open3(password)
21
+ password = Shellwords.escape(password)
22
+
23
+ output = Open3.popen3(STDIN_GREP_COMMAND.join(" "), out: '/dev/null') { |stdin, stdout, stderr, wait_thr|
24
+ stdin.puts "^#{password}$"
25
+ stdin.close
26
+ wait_thr.value
27
+ }
28
+ output.success?
29
+ end
30
+
31
+ def shell_grep_subprocess(password)
32
+ password = Shellwords.escape(password)
33
+
34
+ Subprocess.check_call(STDIN_GREP_COMMAND, stdin: Subprocess::PIPE, stdout: '/dev/null') do |p|
35
+ p.communicate("^#{password}$")
36
+ end
37
+ true
38
+ rescue Subprocess::NonZeroExit
39
+ false
40
+ end
41
+
42
+ def ruby_grep(password)
43
+ File.open(DICTIONARY_PATH).grep(/^#{password}$/)
44
+ end
45
+
46
+ def ruby_loop(password)
47
+ File.open(DICTIONARY_PATH).read_line do |l|
48
+ return true if l.match?(/^#{password}$/)
18
49
  end
50
+ false
51
+ end
19
52
 
53
+ Benchmark.bm(17) do |benchmark|
20
54
  benchmark.report("Shell") do
21
- 25.times { shell_grep(password, dictionary_path) }
55
+ ITERATIONS.times { shell_grep(password) }
56
+ end
57
+
58
+ benchmark.report("Ruby Grep") do
59
+ ITERATIONS.times { ruby_grep(password) }
60
+ end
61
+
62
+ benchmark.report("Ruby Loop") do
63
+ ITERATIONS.times { ruby_grep(password) }
22
64
  end
23
- end
65
+
66
+ benchmark.report("Open3 stdin") do
67
+ ITERATIONS.times { shell_grep_open3(password) }
68
+ end
69
+
70
+ benchmark.report("Subprocess stdin") do
71
+ ITERATIONS.times { shell_grep_subprocess(password) }
72
+ end
73
+ end
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "guard-rspec", "~> 4.7.3"
30
30
  spec.add_development_dependency "activemodel", "~> 5.0"
31
31
  spec.add_development_dependency "i18n", "~> 0.8.1"
32
+ spec.add_development_dependency "subprocess"
32
33
  spec.add_development_dependency "byebug"
33
34
 
34
35
  if RUBY_PLATFORM =~ /darwin/
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nobspw
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Mercier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-21 00:00:00.000000000 Z
11
+ date: 2019-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 0.8.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: subprocess
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: byebug
127
141
  requirement: !ruby/object:Gem::Requirement