mpw 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/ruby
2
2
  # MPW is a software to crypt and manage your passwords
3
- # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
4
- #
3
+ # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im>
4
+ #
5
5
  # This program is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU General Public License
7
7
  # as published by the Free Software Foundation; either version 2
8
8
  # of the License, or (at your option) any later version.
9
- #
9
+ #
10
10
  # This program is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
- #
14
+ #
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,140 +20,169 @@ require 'gpgme'
20
20
  require 'yaml'
21
21
  require 'i18n'
22
22
  require 'fileutils'
23
-
23
+
24
24
  module MPW
25
- class Config
26
-
27
- attr_accessor :error_msg
28
-
29
- attr_accessor :gpg_key
30
- attr_accessor :lang
31
- attr_accessor :config_dir
32
- attr_accessor :default_wallet
33
- attr_accessor :wallet_dir
34
- attr_accessor :gpg_exe
35
- attr_accessor :password
36
-
37
- # Constructor
38
- # @args: config_file -> the specify config file
39
- def initialize(config_file=nil)
40
- @config_file = config_file
41
-
42
- if /darwin/ =~ RUBY_PLATFORM
43
- @config_dir = "#{Dir.home}/Library/Preferences/mpw"
44
- elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
45
- @config_dir = "#{Dir.home}/AppData/Local/mpw"
46
- else
47
- @config_dir = "#{Dir.home}/.config/mpw"
48
- end
49
-
50
- @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? or @config_file.empty?
51
- end
52
-
53
- # Create a new config file
54
- # @args: options -> hash with values
55
- # @rtrn: true if le config file is create
56
- def setup(options)
57
- gpg_key = options[:gpg_key] || @gpg_key
58
- lang = options[:lang] || @lang
59
- wallet_dir = options[:wallet_dir] || @wallet_dir
60
- default_wallet = options[:default_wallet] || @default_wallet
61
- gpg_exe = options[:gpg_exe] || @gpg_exe
62
- password = { numeric: true,
63
- alpha: true,
64
- special: false,
65
- length: 16,
66
- }
67
-
68
- ['numeric', 'special', 'alpha', 'length'].each do |k|
69
- if options.has_key?("pwd_#{k}".to_sym)
70
- password[k.to_sym] = options["pwd_#{k}".to_sym]
71
- elsif not @password.nil? and @password.has_key?(k.to_sym)
72
- password[k.to_sym] = @password[k.to_sym]
73
- end
74
- end
75
-
76
- if not gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
77
- raise I18n.t('error.config.key_bad_format')
78
- end
79
-
80
- wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty?
81
- config = { 'gpg_key' => gpg_key,
82
- 'lang' => lang,
83
- 'wallet_dir' => wallet_dir,
84
- 'default_wallet' => default_wallet,
85
- 'gpg_exe' => gpg_exe,
86
- 'password' => password,
87
- }
88
-
89
- FileUtils.mkdir_p(@config_dir, mode: 0700)
90
- FileUtils.mkdir_p(wallet_dir, mode: 0700)
91
-
92
- File.open(@config_file, 'w') do |file|
93
- file << config.to_yaml
94
- end
95
- rescue Exception => e
96
- raise "#{I18n.t('error.config.write')}\n#{e}"
97
- end
98
-
99
- # Setup a new gpg key
100
- # @args: password -> the GPG key password
101
- # name -> the name of user
102
- # length -> length of the GPG key
103
- # expire -> the time of expire to GPG key
104
- # @rtrn: true if the GPG key is create, else false
105
- def setup_gpg_key(password, name, length = 4096, expire = 0)
106
- if name.to_s.empty?
107
- raise "#{I18n.t('error.config.genkey_gpg.name')}"
108
- elsif password.to_s.empty?
109
- raise "#{I18n.t('error.config.genkey_gpg.password')}"
110
- end
111
-
112
- param = ''
113
- param << '<GnupgKeyParms format="internal">' + "\n"
114
- param << "Key-Type: RSA\n"
115
- param << "Key-Length: #{length}\n"
116
- param << "Subkey-Type: ELG-E\n"
117
- param << "Subkey-Length: #{length}\n"
118
- param << "Name-Real: #{name}\n"
119
- param << "Name-Comment: #{name}\n"
120
- param << "Name-Email: #{@gpg_key}\n"
121
- param << "Expire-Date: #{expire}\n"
122
- param << "Passphrase: #{password}\n"
123
- param << "</GnupgKeyParms>\n"
124
-
125
- ctx = GPGME::Ctx.new
126
- ctx.genkey(param, nil, nil)
127
- rescue Exception => e
128
- raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}"
129
- end
130
-
131
- # Load the config file
132
- def load_config
133
- config = YAML::load_file(@config_file)
134
- @gpg_key = config['gpg_key']
135
- @lang = config['lang']
136
- @wallet_dir = config['wallet_dir']
137
- @default_wallet = config['default_wallet']
138
- @gpg_exe = config['gpg_exe']
139
- @password = config['password'] || {}
140
-
141
- raise if @gpg_key.empty? or @wallet_dir.empty?
142
-
143
- I18n.locale = @lang.to_sym
144
- rescue Exception => e
145
- raise "#{I18n.t('error.config.load')}\n#{e}"
146
- end
147
-
148
- # Check if private key exist
149
- # @rtrn: true if the key exist, else false
150
- def check_gpg_key?
151
- ctx = GPGME::Ctx.new
152
- ctx.each_key(@gpg_key, true) do
153
- return true
154
- end
155
-
156
- return false
157
- end
158
- end
25
+ class Config
26
+ attr_accessor :error_msg
27
+
28
+ attr_accessor :gpg_key
29
+ attr_accessor :lang
30
+ attr_accessor :config_dir
31
+ attr_accessor :default_wallet
32
+ attr_accessor :wallet_dir
33
+ attr_accessor :wallet_paths
34
+ attr_accessor :gpg_exe
35
+ attr_accessor :password
36
+ attr_accessor :pinmode
37
+
38
+ # Constructor
39
+ # @args: config_file -> the specify config file
40
+ def initialize(config_file = nil)
41
+ @config_file = config_file
42
+ @config_dir =
43
+ if /darwin/ =~ RUBY_PLATFORM
44
+ "#{Dir.home}/Library/Preferences/mpw"
45
+ elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
46
+ "#{Dir.home}/AppData/Local/mpw"
47
+ else
48
+ "#{Dir.home}/.config/mpw"
49
+ end
50
+
51
+ @config_file = "#{@config_dir}/mpw.cfg" if @config_file.to_s.empty?
52
+ end
53
+
54
+ # Create a new config file
55
+ # @args: options -> hash with values
56
+ # @rtrn: true if le config file is create
57
+ def setup(**options)
58
+ gpg_key = options[:gpg_key] || @gpg_key
59
+ lang = options[:lang] || @lang
60
+ wallet_dir = options[:wallet_dir] || @wallet_dir
61
+ default_wallet = options[:default_wallet] || @default_wallet
62
+ gpg_exe = options[:gpg_exe] || @gpg_exe
63
+ pinmode = options[:pinmode] || @pinmode
64
+ password = { numeric: true,
65
+ alpha: true,
66
+ special: false,
67
+ length: 16 }
68
+
69
+ %w[numeric special alpha length].each do |k|
70
+ if options.key?("pwd_#{k}".to_sym)
71
+ password[k.to_sym] = options["pwd_#{k}".to_sym]
72
+ elsif !@password.nil? && @password.key?(k.to_sym)
73
+ password[k.to_sym] = @password[k.to_sym]
74
+ end
75
+ end
76
+
77
+ unless gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
78
+ raise I18n.t('error.config.key_bad_format')
79
+ end
80
+
81
+ wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty?
82
+ config = { 'gpg_key' => gpg_key,
83
+ 'lang' => lang,
84
+ 'wallet_dir' => wallet_dir,
85
+ 'default_wallet' => default_wallet,
86
+ 'gpg_exe' => gpg_exe,
87
+ 'password' => password,
88
+ 'pinmode' => pinmode,
89
+ 'wallet_paths' => @wallet_paths }
90
+
91
+ FileUtils.mkdir_p(@config_dir, mode: 0700)
92
+ FileUtils.mkdir_p(wallet_dir, mode: 0700)
93
+
94
+ File.open(@config_file, 'w') do |file|
95
+ file << config.to_yaml
96
+ end
97
+ rescue => e
98
+ raise "#{I18n.t('error.config.write')}\n#{e}"
99
+ end
100
+
101
+ # Setup a new gpg key
102
+ # @args: password -> the GPG key password
103
+ # name -> the name of user
104
+ # length -> length of the GPG key
105
+ # expire -> the time of expire to GPG key
106
+ # @rtrn: true if the GPG key is create, else false
107
+ def setup_gpg_key(password, name, length = 4096, expire = 0)
108
+ raise I18n.t('error.config.genkey_gpg.name') if name.to_s.empty?
109
+ raise I18n.t('error.config.genkey_gpg.password') if password.to_s.empty?
110
+
111
+ param = ''
112
+ param << '<GnupgKeyParms format="internal">' + "\n"
113
+ param << "Key-Type: RSA\n"
114
+ param << "Key-Length: #{length}\n"
115
+ param << "Subkey-Type: ELG-E\n"
116
+ param << "Subkey-Length: #{length}\n"
117
+ param << "Name-Real: #{name}\n"
118
+ param << "Name-Comment: #{name}\n"
119
+ param << "Name-Email: #{@gpg_key}\n"
120
+ param << "Expire-Date: #{expire}\n"
121
+ param << "Passphrase: #{password}\n"
122
+ param << "</GnupgKeyParms>\n"
123
+
124
+ ctx = GPGME::Ctx.new
125
+ ctx.genkey(param, nil, nil)
126
+ rescue => e
127
+ raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}"
128
+ end
129
+
130
+ # Load the config file
131
+ def load_config
132
+ config = YAML.load_file(@config_file)
133
+ @gpg_key = config['gpg_key']
134
+ @lang = config['lang']
135
+ @wallet_dir = config['wallet_dir']
136
+ @wallet_paths = config['wallet_paths'] || {}
137
+ @default_wallet = config['default_wallet']
138
+ @gpg_exe = config['gpg_exe']
139
+ @password = config['password'] || {}
140
+ @pinmode = config['pinmode']
141
+
142
+ raise if @gpg_key.empty? || @wallet_dir.empty?
143
+
144
+ I18n.locale = @lang.to_sym
145
+ rescue => e
146
+ raise "#{I18n.t('error.config.load')}\n#{e}"
147
+ end
148
+
149
+ # Check if private key exist
150
+ # @rtrn: true if the key exist, else false
151
+ def check_gpg_key?
152
+ ctx = GPGME::Ctx.new
153
+ ctx.each_key(@gpg_key, true) do
154
+ return true
155
+ end
156
+
157
+ false
158
+ end
159
+
160
+ # Change the path of one wallet
161
+ # @args: path -> the new directory path
162
+ # wallet -> the wallet name
163
+ def set_wallet_path(path, wallet)
164
+ path = @wallet_dir if path == 'default'
165
+
166
+ return if path == @wallet_dir && File.exist?("#{@wallet_dir}/#{wallet}.mpw")
167
+ return if path == @wallet_paths[wallet]
168
+
169
+ old_wallet_file =
170
+ if @wallet_paths.key?(wallet)
171
+ "#{@wallet_paths[wallet]}/#{wallet}.mpw"
172
+ else
173
+ "#{@wallet_dir}/#{wallet}.mpw"
174
+ end
175
+
176
+ FileUtils.mkdir_p(path) unless Dir.exist?(path)
177
+ FileUtils.mv(old_wallet_file, "#{path}/#{wallet}.mpw") if File.exist?(old_wallet_file)
178
+
179
+ if path == @wallet_dir
180
+ @wallet_paths.delete(wallet)
181
+ else
182
+ @wallet_paths[wallet] = path
183
+ end
184
+
185
+ setup
186
+ end
187
+ end
159
188
  end
@@ -1,109 +1,102 @@
1
1
  #!/usr/bin/ruby
2
2
  # MPW is a software to crypt and manage your passwords
3
- # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
4
- #
3
+ # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im>
4
+ #
5
5
  # This program is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU General Public License
7
7
  # as published by the Free Software Foundation; either version 2
8
8
  # of the License, or (at your option) any later version.
9
- #
9
+ #
10
10
  # This program is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
- #
14
+ #
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
 
19
19
  require 'i18n'
20
-
21
- module MPW
22
- class Item
23
20
 
24
- attr_accessor :id
25
- attr_accessor :group
26
- attr_accessor :host
27
- attr_accessor :protocol
28
- attr_accessor :user
29
- attr_accessor :port
30
- attr_accessor :otp
31
- attr_accessor :comment
32
- attr_accessor :last_edit
33
- attr_accessor :last_sync
34
- attr_accessor :created
21
+ module MPW
22
+ class Item
23
+ attr_accessor :id
24
+ attr_accessor :group
25
+ attr_accessor :host
26
+ attr_accessor :protocol
27
+ attr_accessor :user
28
+ attr_accessor :port
29
+ attr_accessor :otp
30
+ attr_accessor :comment
31
+ attr_accessor :last_edit
32
+ attr_accessor :created
35
33
 
36
- # Constructor
37
- # Create a new item
38
- # @args: options -> a hash of parameter
39
- # raise an error if the hash hasn't the key name
40
- def initialize(options={})
41
- if not options.has_key?(:host) or options[:host].to_s.empty?
42
- raise I18n.t('error.update.host_empty')
43
- end
34
+ # Constructor
35
+ # Create a new item
36
+ # @args: options -> a hash of parameter
37
+ # raise an error if the hash hasn't the key name
38
+ def initialize(**options)
39
+ if !options.key?(:host) || options[:host].to_s.empty?
40
+ raise I18n.t('error.update.host_empty')
41
+ end
44
42
 
45
- if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty?
46
- @id = generate_id
47
- @created = Time.now.to_i
48
- else
49
- @id = options[:id]
50
- @created = options[:created]
51
- @last_edit = options[:last_edit]
52
- options[:no_update_last_edit] = true
53
- end
43
+ if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty?
44
+ @id = generate_id
45
+ @created = Time.now.to_i
46
+ else
47
+ @id = options[:id]
48
+ @created = options[:created]
49
+ @last_edit = options[:last_edit]
50
+ options[:no_update_last_edit] = true
51
+ end
54
52
 
55
- update(options)
56
- end
53
+ update(options)
54
+ end
57
55
 
58
- # Update the item
59
- # @args: options -> a hash of parameter
60
- def update(options={})
61
- if options.has_key?(:host) and options[:host].to_s.empty?
62
- raise I18n.t('error.update.host_empty')
63
- end
56
+ # Update the item
57
+ # @args: options -> a hash of parameter
58
+ def update(**options)
59
+ if options.key?(:host) && options[:host].to_s.empty?
60
+ raise I18n.t('error.update.host_empty')
61
+ end
64
62
 
65
- @group = options[:group] if options.has_key?(:group)
66
- @host = options[:host] if options.has_key?(:host)
67
- @protocol = options[:protocol] if options.has_key?(:protocol)
68
- @user = options[:user] if options.has_key?(:user)
69
- @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty?
70
- @otp = options[:otp] if options.has_key?(:otp)
71
- @comment = options[:comment] if options.has_key?(:comment)
72
- @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit)
73
- end
63
+ @group = options[:group] if options.key?(:group)
64
+ @host = options[:host] if options.key?(:host)
65
+ @protocol = options[:protocol] if options.key?(:protocol)
66
+ @user = options[:user] if options.key?(:user)
67
+ @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty?
68
+ @otp = options[:otp] if options.key?(:otp)
69
+ @comment = options[:comment] if options.key?(:comment)
70
+ @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit)
71
+ end
74
72
 
75
- # Update last_sync
76
- def set_last_sync
77
- @last_sync = Time.now.to_i
78
- end
73
+ # Delete all data
74
+ def delete
75
+ @id = nil
76
+ @group = nil
77
+ @host = nil
78
+ @protocol = nil
79
+ @user = nil
80
+ @port = nil
81
+ @otp = nil
82
+ @comment = nil
83
+ @created = nil
84
+ @last_edit = nil
85
+ end
79
86
 
80
- # Delete all data
81
- def delete
82
- @id = nil
83
- @group = nil
84
- @host = nil
85
- @protocol = nil
86
- @user = nil
87
- @port = nil
88
- @otp = nil
89
- @comment = nil
90
- @created = nil
91
- @last_edit = nil
92
- @last_sync = nil
93
- end
87
+ def empty?
88
+ @id.to_s.empty?
89
+ end
94
90
 
95
- def empty?
96
- return @id.to_s.empty?
97
- end
91
+ def nil?
92
+ false
93
+ end
98
94
 
99
- def nil?
100
- return false
101
- end
95
+ private
102
96
 
103
- # Generate an random id
104
- private
105
- def generate_id
106
- return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join
107
- end
108
- end
97
+ # Generate an random id
98
+ def generate_id
99
+ [*('A'..'Z'), *('a'..'z'), *('0'..'9')].sample(16).join
100
+ end
101
+ end
109
102
  end