lockr 0.3.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ require 'lockr/pwdstore'
4
4
  class AddAction < AesAction
5
5
 
6
6
  def initialize(id,url,username,pwd,keyfile,vault)
7
- keyfilehash = calculate_hash( keyfile)
7
+ keyfilehash = FileUtils.calculate_sha512_hash( keyfile)
8
8
 
9
9
  pwd_directory = load_from_vault( vault)
10
10
 
@@ -1,47 +1,12 @@
1
1
  require 'openssl'
2
2
  require 'lockr/encryption/aes'
3
+ require 'lockr/fileutils'
3
4
 
4
5
  class BaseAction
5
- def calculate_hash( filename)
6
- sha1 = OpenSSL::Digest::SHA512.new
7
-
8
- File.open( filename) do |file|
9
- buffer = ''
10
-
11
- # Read the file 512 bytes at a time
12
- while not file.eof
13
- file.read(512, buffer)
14
- sha1.update(buffer)
15
- end
16
- end
17
-
18
- sha1.to_s
19
- end
6
+ include FileUtils
20
7
 
21
8
  def save_to_vault( storelist, vault)
22
- rotate_vault( vault)
23
-
24
- File.open( vault, 'w') do |f|
25
- f.write( storelist.to_yaml)
26
- end
27
- end
28
-
29
- def rotate_vault( vault)
30
- return unless File.exists?(vault)
31
-
32
- # move old files first
33
- max_files = 2 # = 3 - 1
34
- max_files.downto( 0) { |i|
35
-
36
- if i == 0
37
- File.rename( vault, "#{vault}_#{i}")
38
- else
39
- j = i - 1
40
- if File.exists?("#{vault}_#{j}")
41
- File.rename( "#{vault}_#{j}", "#{vault}_#{i}")
42
- end
43
- end
44
- }
9
+ FileUtils.store_obj_yaml( vault, storelist)
45
10
  end
46
11
 
47
12
  # loads the datastructure for the password sets from the file
@@ -58,14 +23,6 @@ class BaseAction
58
23
  # :username => PasswordStore
59
24
  # }
60
25
  def load_from_vault( vault)
61
- storelist = {}
62
-
63
- if File.exist?( vault)
64
- File.open( vault, 'r') do |f|
65
- storelist = YAML::load(f)
66
- end
67
- end
68
-
69
- storelist
26
+ FileUtils.load_obj_yaml( vault)
70
27
  end
71
28
  end
@@ -12,7 +12,7 @@ class ListAction < AesAction
12
12
  out << "Id: #{id}"
13
13
  }
14
14
  else
15
- keyfilehash = calculate_hash( keyfile)
15
+ keyfilehash = FileUtils.calculate_sha512_hash( keyfile)
16
16
  pwd_directory.each { |oid,value|
17
17
  pwd_directory_id = YAML::load(decrypt( value[:enc], keyfilehash, value[:salt]))
18
18
  pwd_directory_id.each { |username, pwdstore|
@@ -4,7 +4,7 @@ require 'lockr/pwdstore'
4
4
  class RemoveAction < AesAction
5
5
 
6
6
  def initialize(id,username,keyfile,vault)
7
- keyfilehash = calculate_hash( keyfile)
7
+ keyfilehash = FileUtils.calculate_sha512_hash( keyfile)
8
8
  pwd_directory = load_from_vault( vault)
9
9
 
10
10
  unless pwd_directory.has_key?( id)
@@ -3,7 +3,7 @@ require 'lockr/action/aes'
3
3
  class ShowAction < AesAction
4
4
 
5
5
  def initialize(id,username,keyfile, vault)
6
- keyfilehash = calculate_hash( keyfile)
6
+ keyfilehash = FileUtils.calculate_sha512_hash( keyfile)
7
7
 
8
8
  pwd_directory = load_from_vault( vault)
9
9
 
@@ -0,0 +1,74 @@
1
+ module FileUtils
2
+
3
+ # rotate the provided file with a maximum of 'limit' backups
4
+ # renamed filed will be named file_0, file_1, ...
5
+ def FileUtils.rotate_file( file, limit)
6
+ return unless File.exists?(file)
7
+
8
+ # move old files first
9
+ max_files = limit - 1
10
+ max_files.downto( 0) { |i|
11
+
12
+ if i == 0
13
+ FileUtils.copy( file, "#{file}_#{i}")
14
+ else
15
+ j = i - 1
16
+ if File.exists?("#{file}_#{j}")
17
+ FileUtils.copy( "#{file}_#{j}", "#{file}_#{i}")
18
+ end
19
+ end
20
+ }
21
+
22
+ puts "Rotated local vault file(s)"
23
+ end
24
+
25
+ # copy file_src to file_target
26
+ def FileUtils.copy( file_src, file_target)
27
+ return unless File.exists?( file_src)
28
+
29
+ dst = File.new( file_target, 'w')
30
+ File.open( file_src, 'r') do |src|
31
+ dst.write( src.read)
32
+ end
33
+ dst.close
34
+ end
35
+
36
+ # store an object as yaml to file
37
+ def FileUtils.store_obj_yaml( file, object)
38
+ File.open( file, 'w') do |f|
39
+ f.write( object.to_yaml)
40
+ end
41
+ end
42
+
43
+ # load an yaml object from file
44
+ def FileUtils.load_obj_yaml( file)
45
+ object = {}
46
+
47
+ unless File.exist?( file)
48
+ return object
49
+ end
50
+
51
+ File.open( file, 'r') do |f|
52
+ object = YAML::load(f)
53
+ end
54
+
55
+ object
56
+ end
57
+
58
+ # calculate the sha512 hash of a file
59
+ def FileUtils.calculate_sha512_hash( filename)
60
+ sha512 = OpenSSL::Digest::SHA512.new
61
+
62
+ File.open( filename) do |file|
63
+ buffer = ''
64
+
65
+ # Read the file 512 bytes at a time
66
+ while not file.eof
67
+ file.read(512, buffer)
68
+ sha512.update(buffer)
69
+ end
70
+ end
71
+
72
+ sha512.to_s
73
+ end
74
+ end
data/lib/lockr/sftp.rb ADDED
@@ -0,0 +1,100 @@
1
+ require 'lockr/config'
2
+ require 'net/sftp'
3
+ require 'set'
4
+ require 'lockr/fileutils'
5
+
6
+ class SFTP
7
+ include FileUtils
8
+
9
+ # upload the vault via sftp to the location specified in the configuration
10
+ def upload( config, vault)
11
+ cfg_sftp = get_sftp_config( config)
12
+ remote_file = File.join( cfg_sftp[:directory], File.basename(vault))
13
+ Net::SFTP.start( cfg_sftp[:hostname], cfg_sftp[:username]) do |sftp|
14
+
15
+ # TODO check remote checksum to make sure upload is necessary
16
+ rotate_sftp_file( sftp, remote_file, 3)
17
+
18
+ # upload a file or directory to the remote host
19
+ sftp.upload!( vault, remote_file)
20
+ puts "Uploaded vault to host '#{cfg_sftp[:hostname]}' by SFTP"
21
+ end
22
+ end
23
+
24
+ # rotate the provided file with a maximum of 'limit' backups
25
+ # renamed filed will be named file_0, file_1, ...
26
+ def rotate_sftp_file( sftp, file, limit)
27
+ return unless file_exists( sftp, file)
28
+
29
+ # move old files first
30
+ max_files = limit - 1
31
+ max_files.downto( 0) { |i|
32
+
33
+ if i == 0
34
+ sftp.rename( file, "#{file}_#{i}")
35
+ else
36
+ j = i - 1
37
+ next unless file_exists( sftp, "#{file}_#{j}")
38
+ sftp.rename( "#{file}_#{j}", "#{file}_#{i}")
39
+ end
40
+ }
41
+
42
+ puts "Rotated remote vault file(s)"
43
+ end
44
+
45
+ # check if the file exists on the given sftp connection
46
+ def file_exists( sftp, file)
47
+ files = get_dir_listing( sftp, File.dirname(file))
48
+ files.include?( File.basename(file))
49
+ end
50
+
51
+ # get the file listing of a remote directory
52
+ def get_dir_listing( sftp, dir)
53
+ list = []
54
+
55
+ sftp.dir.foreach(dir) do |entry|
56
+ list << entry.name
57
+ end
58
+
59
+ Set.new(list)
60
+ end
61
+
62
+ # download the vault via sftp to the location specified in the configuration
63
+ def download( config, vault)
64
+ cfg_sftp = get_sftp_config( config)
65
+
66
+ Net::SFTP.start( cfg_sftp[:hostname], cfg_sftp[:username]) do |sftp|
67
+
68
+ # TODO check if remote file is same as local (checksum?)
69
+ rotate_file( vault, 3)
70
+
71
+ # upload a file or directory to the remote host
72
+ sftp.download!( File.join( cfg_sftp[:directory], File.basename(vault)), vault)
73
+ puts "Downloaded vault from host '#{cfg_sftp[:hostname]}' by SFTP"
74
+ end
75
+ end
76
+
77
+ # check config for section lockr and subsection sftp. then check for keys
78
+ # :hostname, :username and :directory. if anything is missing, raise ArgumentError
79
+ # returns sftp configuration hash
80
+ def get_sftp_config( config)
81
+ unless config.config.has_key?( :lockr)
82
+ raise ArgumentError, 'config has no "lockr" section'
83
+ end
84
+
85
+ cfg = config.config[:lockr]
86
+
87
+ unless cfg.has_key?( :sftp)
88
+ raise ArgumentError, 'config has no "sftp" section'
89
+ end
90
+
91
+ cfg_sftp = cfg[:sftp]
92
+
93
+ unless cfg_sftp.has_key?( :hostname) and cfg_sftp.has_key?( :username) and cfg_sftp.has_key?( :directory)
94
+ raise ArgumentError, 'config "sftp" section must have keys :host, :username and :directory'
95
+ end
96
+
97
+ cfg_sftp
98
+ end
99
+
100
+ end
data/lib/lockr/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module LockrVer
2
- VERSION = "0.3.0"
3
- DATE = "2012-08-13"
2
+ VERSION = "0.4.2"
3
+ DATE = "2012-08-19"
4
4
  end
data/lib/lockr.rb CHANGED
@@ -10,16 +10,19 @@ require 'lockr/action/remove'
10
10
  require 'lockr/action/show'
11
11
  require 'lockr/config'
12
12
  require 'lockr/pwdgen'
13
+ require 'lockr/sftp'
13
14
  require 'lockr/version'
15
+ require 'lockr/fileutils'
14
16
 
15
17
  class Lockr
16
18
 
17
19
  def run()
18
20
  options = parse_options()
19
- merge_config( options)
21
+ configfile = Configuration.new()
22
+ merge_config( configfile, options)
20
23
  validate_options( options)
21
24
  acquire_additional_input( options)
22
- process_actions( options)
25
+ process_actions( configfile, options)
23
26
  end
24
27
 
25
28
  def parse_options()
@@ -55,7 +58,17 @@ class Lockr
55
58
  opts.on( '-g', '--genpwd PARAMS', 'generate a random password (based on the optional PARAMS)') do |params|
56
59
  options[:generatepwd] = params
57
60
  end
61
+
62
+ options[:download] = nil
63
+ opts.on( '-d', '--download', 'download latest vault from configured sftp location before executing action') do |d|
64
+ options[:download] = true
65
+ end
58
66
 
67
+ options[:upload] = nil
68
+ opts.on( '-u', '--upload', 'upload vault to configured sftp location after executing action') do |d|
69
+ options[:upload] = true
70
+ end
71
+
59
72
  # This displays the help screen, all programs are
60
73
  # assumed to have this option.
61
74
  opts.on( '-h', '--help', 'Display this screen' ) do
@@ -82,9 +95,7 @@ class Lockr
82
95
  options
83
96
  end
84
97
 
85
- def merge_config( options)
86
- configfile = Configuration.new()
87
-
98
+ def merge_config( configfile, options)
88
99
  if configfile.config.nil?
89
100
  return
90
101
  end
@@ -138,7 +149,15 @@ class Lockr
138
149
  end
139
150
  end
140
151
 
141
- def process_actions( options)
152
+ def process_actions( configfile, options)
153
+ rotate_required = ( ! options[:download].nil? ) || ( ! %w{a add r remove}.index( options[:action]).nil? )
154
+ FileUtils.rotate_file( options[:vault], 3) if rotate_required
155
+
156
+ unless options[:download].nil?
157
+ sftp = SFTP.new
158
+ sftp.download( configfile, options[:vault])
159
+ end
160
+
142
161
  begin
143
162
  case options[:action]
144
163
  when 'a', 'add'
@@ -162,5 +181,10 @@ class Lockr
162
181
  say( "<%= color('Invalid keyfile', :red) %>")
163
182
  exit 42
164
183
  end
184
+
185
+ unless options[:upload].nil?
186
+ sftp = SFTP.new
187
+ sftp.upload( configfile, options[:vault])
188
+ end
165
189
  end
166
190
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lockr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,31 +9,43 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-13 00:00:00.000000000 Z
12
+ date: 2012-08-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: highline
16
- requirement: &70208522621980 !ruby/object:Gem::Requirement
16
+ requirement: &70292937547480 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 1.6.13
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70208522621980
24
+ version_requirements: *70292937547480
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70208522620300 !ruby/object:Gem::Requirement
27
+ requirement: &70292937546980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 1.1.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70208522620300
36
- description: Store your passwords AES encrypted in a simple yaml file
35
+ version_requirements: *70292937546980
36
+ - !ruby/object:Gem::Dependency
37
+ name: net-sftp
38
+ requirement: &70292937546520 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 2.0.5
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70292937546520
47
+ description: Lockr is a command line based password manager. Passwords are stored
48
+ AES-encrypted in a file on your own system.
37
49
  email: info@byteblues.com
38
50
  executables:
39
51
  - lockr
@@ -49,8 +61,10 @@ files:
49
61
  - lib/lockr/action/show.rb
50
62
  - lib/lockr/encryption/aes.rb
51
63
  - lib/lockr/config.rb
64
+ - lib/lockr/fileutils.rb
52
65
  - lib/lockr/pwdgen.rb
53
66
  - lib/lockr/pwdstore.rb
67
+ - lib/lockr/sftp.rb
54
68
  - lib/lockr/version.rb
55
69
  - !binary |-
56
70
  YmluL2xvY2ty
@@ -77,5 +91,5 @@ rubyforge_project:
77
91
  rubygems_version: 1.8.10
78
92
  signing_key:
79
93
  specification_version: 3
80
- summary: Safe password storage
94
+ summary: Command line based password manager
81
95
  test_files: []