osp 0.1.0.pre.dev.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 91fa1ed62524c4d5a625fc41b705e53ec07c1025
4
+ data.tar.gz: 4953a9cc50c9ae298912a8829ad040caa0a273e1
5
+ SHA512:
6
+ metadata.gz: a3b038055e9eabb2b95739973349a846db72e4dab13fb75d02eac627284acd91e4d640804edc42158ddad3933cbe80f272d5a57e7308280a15cad09aa7edc188
7
+ data.tar.gz: 10ed0c220116da7cb8f1b4d72d5dcdd27e9eafb55a8a222032e82e22bc673c7ac3b66263215337dc37caf58c68dd19a63ed66025a015c082407c1b630d019fe9
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ /.bundle/
2
+ .setup
3
+ CHANGELOG-*.txt
4
+ /releases/
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1
4
+ - 2.2
5
+ before_install:
6
+ - ruby --version
7
+ script:
8
+ - make test
9
+ - make install
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+
2
+ source 'https://rubygems.org'
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ osp (0.1.0.pre.dev.1)
5
+ highline (~> 1.7)
6
+ msgpack (~> 0.7)
7
+ rainbow (~> 2.0)
8
+ thefox-ext (~> 1.2)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ highline (1.7.8)
14
+ minitest (5.8.3)
15
+ msgpack (0.7.1)
16
+ rainbow (2.0.0)
17
+ thefox-ext (1.2.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ bundler (~> 1.10)
24
+ minitest (~> 5.8)
25
+ osp!
26
+
27
+ BUNDLED WITH
28
+ 1.10.2
data/Makefile ADDED
@@ -0,0 +1,8 @@
1
+
2
+ GEM_NAME = osp
3
+
4
+ include Makefile.common
5
+
6
+ .PHONY: test
7
+ test:
8
+ RUBYOPT=-w ./tests/ts_all.rb
data/Makefile.common ADDED
@@ -0,0 +1,51 @@
1
+
2
+ # Ruby Common Big
3
+ # 2015-12-15
4
+
5
+ MV = mv -nv
6
+ RM = rm -rf
7
+ MKDIR = mkdir -p
8
+ BUNDLER = bundle
9
+ BUNDLER_OPTIONS = --jobs=5 --retry=3
10
+ GEMSPEC_FILE = $(GEM_NAME).gemspec
11
+
12
+ .PHONY: all $(ALL_TARGETS_EXT)
13
+ all: setup
14
+
15
+ .PHONY: setup
16
+ setup: .setup
17
+
18
+ .setup:
19
+ $(BUNDLER) install $(BUNDLER_OPTIONS)
20
+ touch $@
21
+
22
+ .PHONY: install
23
+ install:
24
+ gem_file=$$(gem build $(GEMSPEC_FILE) | grep 'File:' | tail -1 | awk '{ print $$2 }'); \
25
+ sudo gem install $$gem_file; \
26
+ $(RM) $$gem_file
27
+
28
+ .PHONY: uninstall
29
+ uninstall:
30
+ sudo gem uninstall $(GEM_NAME)
31
+
32
+ .PHONY: update
33
+ update:
34
+ $(BUNDLER) update
35
+
36
+ .PHONY: clean
37
+ clean:
38
+ $(RM) .setup
39
+
40
+ .PHONY: release
41
+ release: | releases
42
+ set -e; \
43
+ gem_file=$$(gem build $(GEMSPEC_FILE) | grep 'File:' | tail -1 | awk '{ print $$2 }'); \
44
+ dst="releases/$$gem_file"; \
45
+ [ ! -f $$dst ]; \
46
+ $(MV) $$gem_file releases; \
47
+ gem push $$dst; \
48
+ echo 'done'
49
+
50
+ releases:
51
+ $(MKDIR) $@
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # One Shall Pass for Command Line
2
+
3
+ ## Project Links
4
+
5
+ - [Gem](https://rubygems.org/gems/osp)
6
+ - [Travis CI Repository](https://travis-ci.org/TheFox/osp)
7
+
8
+ ## Weblinks
9
+
10
+ - [maxtaco/oneshallpass](https://github.com/maxtaco/oneshallpass)
11
+ - [Ruby OpenSSL HMAC](http://ruby-doc.org/stdlib-2.2.4/libdoc/openssl/rdoc/OpenSSL/HMAC.html)
12
+ - [Ruby OpenSSL PKCS5](http://ruby-doc.org/stdlib-2.2.2/libdoc/openssl/rdoc/OpenSSL/PKCS5.html)
13
+ - [Ruby AES Encryption using OpenSSL](https://gist.github.com/byu/99651)
14
+
15
+ ## License
16
+ Copyright (C) 2015 Christian Mayer <http://fox21.at>
17
+
18
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
19
+
20
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
data/bin/catmp ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: UTF-8
3
+
4
+ raise 'Ruby >=2.1 required' unless RUBY_VERSION >= '2.1.0'
5
+
6
+ require 'optparse'
7
+ require 'yaml'
8
+ require 'pp'
9
+
10
+ require 'bundler/setup'
11
+ require 'msgpack'
12
+
13
+
14
+ options = {
15
+ :path => nil,
16
+ :yaml => false,
17
+ }
18
+ opts = OptionParser.new do |opts|
19
+ opts.banner = 'Usage: catmp'
20
+ opts.separator('')
21
+
22
+ # opts.on('-p', '--path <path>', 'Path msgpack file.') do |path|
23
+ # options[:path] = path
24
+ # end
25
+
26
+ opts.on('-y', '--yaml', 'Output in YAML format.') do
27
+ options[:yaml] = true
28
+ end
29
+
30
+ opts.on_tail('-h', '--help', 'Show this message.') do
31
+ puts opts
32
+ puts
33
+ exit 3
34
+ end
35
+ end
36
+ #ARGV << '-h' if ARGV.count == 0
37
+ args = opts.parse(ARGV)
38
+
39
+ if args.count > 0
40
+ options[:path] = args.shift
41
+
42
+ if !options[:path].nil?
43
+ ar = MessagePack.unpack(File.binread(options[:path]))
44
+
45
+ if options[:yaml]
46
+ print YAML.dump(ar)
47
+ else
48
+ pp ar
49
+ end
50
+ else
51
+ raise 'FATAL ERROR: path invalid.'
52
+ end
53
+ else
54
+ opts.parse(['-h'])
55
+ end
56
+
data/bin/osp ADDED
@@ -0,0 +1,384 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: UTF-8
3
+
4
+ raise 'Ruby >=2.1 required' unless RUBY_VERSION >= '2.1.0'
5
+
6
+ require 'optparse'
7
+ require 'fileutils'
8
+ #require 'securerandom'
9
+ #require 'openssl'
10
+ #require 'base64'
11
+ # require 'yaml/store'
12
+ require 'pp'
13
+
14
+ require 'bundler/setup'
15
+ #require 'highline/import'
16
+ require 'highline'
17
+ require 'rainbow'
18
+ require 'msgpack'
19
+ require 'osp'
20
+
21
+ #msg = [1,2,3].to_msgpack
22
+ #MessagePack.unpack(msg)
23
+
24
+
25
+ options = {
26
+ :database_path => "#{Dir.home}/.osp",
27
+ }
28
+ opts = OptionParser.new do |opts|
29
+ opts.banner = 'Usage: osp'
30
+ opts.separator('')
31
+
32
+ opts.on('-d', '--database <path>', 'Path to the database file.') do |path|
33
+ options[:database_path] = path
34
+ end
35
+
36
+ opts.on_tail('-h', '--help', 'Show this message.') do
37
+ puts opts
38
+ puts
39
+ exit 3
40
+ end
41
+ end
42
+ #ARGV << '-h' if ARGV.count == 0
43
+ args = opts.parse(ARGV)
44
+
45
+
46
+ @cli = HighLine.new
47
+
48
+ puts "OSP - OneShallPass #{TheFox::OSP::VERSION}"
49
+ puts TheFox::OSP::HOMEPAGE
50
+ puts
51
+
52
+ puts 'Master Login'
53
+
54
+ # email = @cli.ask(' Email: ')
55
+ puts ' Email: xyz@example.com'
56
+ # password = @cli.ask('Password: '){ |q| q.echo = '*' }
57
+ puts 'Password: xyz'
58
+
59
+ Console.cursor_jump_to_column
60
+ Console.cursor_up(2)
61
+ Console.screen_clear_to_bottom
62
+
63
+ puts ' Email: *****'
64
+ puts 'Password: *****'
65
+ puts
66
+
67
+ email = 'xyz@example.com'
68
+ password = 'xyz'
69
+
70
+ database = {
71
+ 'meta' => {
72
+ 'version' => 1,
73
+ 'created_at' => DateTime.now.to_s,
74
+ 'updated_at' => DateTime.now.to_s,
75
+ },
76
+ 'hosts' => {}
77
+ }
78
+ has_database = false
79
+ has_database_changes = false
80
+ if File.exist?(options[:database_path])
81
+ puts "Found database file: #{options[:database_path]}",
82
+ 'Try to open it ...'
83
+
84
+ begin
85
+ database = MessagePack.unpack(File.binread(options[:database_path]))
86
+ database['hosts'] = database['hosts'].map{ |name, host| [name, TheFox::OSP::Host.from_h(host)] }.to_h
87
+ rescue Exception => e
88
+ puts "FATAL ERROR: couldn't open database:"
89
+ puts "'#{e}'"
90
+
91
+ exit
92
+ end
93
+ end
94
+
95
+ printf "Calculating base hash: #{TheFox::OSP::HASHES_N} (#{TheFox::OSP::HASHES_EXP}-bit) - please wait ..."
96
+
97
+ osp = TheFox::OSP::OSP.new(email, password, TheFox::OSP::HASHES_N)
98
+ osp.key_derivation
99
+ puts ' done'
100
+
101
+ database['hosts'].each{ |name, host| host.osp = osp }
102
+
103
+ def password_callback_method(step, pw)
104
+ printf '.'
105
+ end
106
+ osp.password_callback_method = self.method('password_callback_method')
107
+
108
+ def host_show(host, regenerate_password = false)
109
+ if !host.has_generated_password? || regenerate_password
110
+ print 'Generate password '
111
+ host.generate_password(regenerate_password)
112
+ puts ' done'
113
+ end
114
+
115
+ puts
116
+ puts " Name: #{host.name}"
117
+ puts "Generation: #{host.generation}"
118
+ puts " Length: #{host.length}"
119
+ puts " Symbols: #{host.symbols}"
120
+ puts " Hashes: #{host.hashes}"
121
+ puts " Password: #{host.password}"
122
+ end
123
+
124
+ def host_edit(osp, host = nil)
125
+ host = TheFox::OSP::Host.new(osp) if host.nil?
126
+
127
+ tmp = @cli.ask(' Name: ' + (!host.name.nil? ? "[#{host.name}]" : '') + ' ').strip.to_s
128
+ # puts "name: '#{tmp}' #{tmp.class}"
129
+
130
+ host.name = tmp if tmp != ''
131
+ # puts "name: '#{host.name}' #{host.name.class}"
132
+
133
+ host.name = nil if host.name == ''
134
+ # puts "name: '#{host.name}' #{host.name.class}"
135
+
136
+ if host.name.nil?
137
+ # puts "No host input."
138
+ return nil
139
+ end
140
+
141
+ host.generation = @cli.ask("Generation: [#{host.generation}] ", Integer){ |q|
142
+ q.default = host.generation
143
+ q.in = 1..99 }.to_i
144
+
145
+ host.length = @cli.ask(" Length: [#{host.length}] ", Integer){ |q|
146
+ q.default = host.length
147
+ q.in = TheFox::OSP::PASSWORD_MIN_SIZE..TheFox::OSP::PASSWORD_MAX_SIZE }.to_i
148
+
149
+ host.symbols = @cli.ask(" Symbols: [#{host.symbols}] ", Integer){ |q|
150
+ q.default = host.symbols
151
+ q.in = 0..3 }.to_i
152
+
153
+ host.updated_at = DateTime.now
154
+
155
+ host
156
+ end
157
+
158
+ actions = ['begin']
159
+ while true
160
+ case actions.pop
161
+ when 'begin'
162
+ puts
163
+ puts "Type '?' for help."
164
+ when 'n'
165
+ puts
166
+ host = host_edit(osp)
167
+ if !host.nil?
168
+ host_show(host)
169
+ puts
170
+
171
+ add = @cli.ask('Add to database? [yN] ', String){ |q| q.character = true }.strip.downcase
172
+ add = 'n' if add == ''
173
+ puts "Answer: '#{add}'"
174
+
175
+ if add == 'y'
176
+ has_database_changes = true
177
+
178
+ database['hosts'][host.name] = host
179
+ end
180
+ else
181
+ puts "ERROR: hostname can't be nothing."
182
+ end
183
+ when 'l'
184
+ puts
185
+ puts 'List Hosts'
186
+ puts
187
+
188
+ hosts_n = database['hosts'].count
189
+ format = '%' + hosts_n.to_s.length.to_s + 'd'
190
+
191
+ # puts "format: '#{format}'"
192
+
193
+ n = 0
194
+ database['hosts'].values.each do |host|
195
+ n += 1
196
+ # pp host
197
+ printf "#{format}. %s\n", n, host.name
198
+ end
199
+ when 's'
200
+ found_hosts = []
201
+
202
+ search_actions = ['begin']
203
+ while true
204
+ case search_actions.pop
205
+ when 'begin'
206
+ puts
207
+ puts 'Entering search submenu.'
208
+
209
+ search_actions << 's'
210
+ when 's'
211
+ puts
212
+
213
+ host_name = @cli.ask('Search host names: ', String).strip.downcase
214
+ re = Regexp.new(host_name, Regexp::IGNORECASE)
215
+
216
+ found_hosts = database['hosts'].select{ |name, host| re.match(host.name) }
217
+
218
+ search_actions << 'l'
219
+ when 'l'
220
+ puts
221
+ if found_hosts.count > 0
222
+ puts "#{found_hosts.count} host(s) found:"
223
+
224
+ hosts_n = found_hosts.count
225
+ format = '%' + hosts_n.to_s.length.to_s + 'd'
226
+ n = 0
227
+ found_hosts.each do |name, host|
228
+ n += 1
229
+ printf "#{format}. %s\n", n, host.name
230
+ end
231
+ else
232
+ puts 'No hosts found.'
233
+ end
234
+ when 'i'
235
+ puts
236
+ if found_hosts.count > 0
237
+ index = @cli.ask('Show host, select by number: ', Integer){ |q|
238
+ q.character = true if found_hosts.count < 10
239
+ q.in = 1..(found_hosts.count) }.to_i
240
+
241
+ puts
242
+ puts "Host ##{index} selected:"
243
+ index -= 1
244
+ selected_host = nil
245
+ begin
246
+ selected_host = found_hosts.values[index]
247
+ rescue Exception => e
248
+ puts "ERROR: #{e}"
249
+ end
250
+
251
+ if !selected_host.nil?
252
+ host_show(selected_host)
253
+ end
254
+ else
255
+ puts 'No hosts found.'
256
+ end
257
+ when 'e'
258
+ puts
259
+ if found_hosts.count > 0
260
+ index = @cli.ask('Edit, select host by number: ', Integer){ |q|
261
+ q.character = true if found_hosts.count < 10
262
+ q.in = 1..(found_hosts.count) }.to_i
263
+
264
+ puts
265
+ puts "Host ##{index} selected:"
266
+ index -= 1
267
+ selected_host = nil
268
+ begin
269
+ selected_host = found_hosts.values[index].clone
270
+ rescue Exception => e
271
+ puts "ERROR: #{e}"
272
+ end
273
+
274
+ if !selected_host.nil?
275
+ host_edit(osp, selected_host)
276
+ host_show(selected_host)
277
+
278
+ database['hosts'][selected_host.name] = selected_host
279
+
280
+ has_database_changes = true
281
+ end
282
+ else
283
+ puts 'No hosts found.'
284
+ end
285
+ # when 'd'
286
+ # puts
287
+ # if found_hosts.count > 0
288
+ # puts 'Delete'
289
+ # puts
290
+ # else
291
+ # puts 'No hosts found.'
292
+ # end
293
+ when 'q'
294
+ break
295
+ when '?'
296
+ puts
297
+ puts 'Search-menu help:'
298
+ puts "\ts - New search."
299
+ puts "\tl - List found hosts."
300
+ puts "\ti - Print informations about a host found by a search."
301
+ puts "\te - Edit a host found by search."
302
+ # puts "\td - Delete a host found by search."
303
+ puts "\tq - Quit search."
304
+ puts "\t? - Print help."
305
+ else
306
+ puts "WARNING: invalid input. Type '?' for help."
307
+ end
308
+
309
+ next if search_actions.count > 0
310
+
311
+ puts
312
+ search_actions << @cli.ask('[slieq?] >> '){ |q| q.character = true }.downcase
313
+ end
314
+ when 'x'
315
+ actions << 'q'
316
+ actions << 'w'
317
+ when 'w'
318
+ if has_database_changes
319
+ tmp = "#{options[:database_path]}~"
320
+ backup = "#{options[:database_path]}~backup"
321
+
322
+ database['meta']['updated_at'] = DateTime.now.to_s
323
+
324
+ if File.exist?(options[:database_path])
325
+ puts "Backup old file to '#{backup}'."
326
+ FileUtils.mv(options[:database_path], backup)
327
+ end
328
+
329
+ puts "Write temp file to '#{tmp}'."
330
+ db_c = database.clone
331
+ db_c['hosts'] = db_c['hosts'].map{ |name, host| [name, host.to_h] }.to_h
332
+ File.binwrite(tmp, db_c.to_msgpack)
333
+
334
+ puts "Finally move temp file to '#{options[:database_path]}'."
335
+ FileUtils.mv(tmp, options[:database_path])
336
+
337
+ has_database_changes = false
338
+ else
339
+ puts 'Nothing changed, nothing written.'
340
+ end
341
+ when 'q'
342
+ if has_database_changes
343
+ puts
344
+ puts 'You have unsaved database changes.'
345
+
346
+ save = @cli.ask('Would you like to save the database? [Yn] ', String){ |q| q.character = true }.strip.downcase
347
+ save = 'y' if save == ''
348
+ puts "Answer: '#{save}'"
349
+
350
+ if save == 'y'
351
+ actions << 'x'
352
+ else
353
+ really = @cli.ask('Really? [yN] ', String){ |q| q.character = true }.strip.downcase
354
+ really = 'y' if really == ''
355
+ puts "Answer: '#{really}'"
356
+
357
+ if really == 'y'
358
+ has_database_changes = false
359
+ actions << 'q'
360
+ end
361
+ end
362
+ else
363
+ puts 'Quit.'
364
+ break
365
+ end
366
+ when '?'
367
+ puts
368
+ puts 'Main-menu help:'
369
+ puts "\tn - New password."
370
+ puts "\tl - List hosts from database."
371
+ puts "\ts - Search submenu."
372
+ puts "\tx - Same as wq."
373
+ puts "\tw - Write database to file."
374
+ puts "\tq - Quit."
375
+ puts "\t? - Print help."
376
+ else
377
+ puts "WARNING: invalid input. Type '?' for help."
378
+ end
379
+
380
+ next if actions.count > 0
381
+
382
+ puts
383
+ actions << @cli.ask('[nlsxwq?] > '){ |q| q.character = true }.downcase
384
+ end
data/lib/ext/string.rb ADDED
@@ -0,0 +1,8 @@
1
+
2
+ require 'thefox-ext'
3
+
4
+ class String
5
+ def is_valid?
6
+ is_upper? || is_lower? || is_digit?
7
+ end
8
+ end