mpw 2.0.3 → 3.0.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.
data/bin/mpw-server DELETED
@@ -1,78 +0,0 @@
1
- #!/usr/bin/ruby
2
- # author: nishiki
3
- # mail: nishiki@yaegashi.fr
4
- # info: a simple script who manage your passwords
5
-
6
- require 'rubygems'
7
- require 'optparse'
8
- require 'pathname'
9
- require 'locale'
10
- require 'i18n'
11
- require 'mpw/server'
12
-
13
- APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath)
14
-
15
- # --------------------------------------------------------- #
16
- # Set local
17
- # --------------------------------------------------------- #
18
-
19
- lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
20
-
21
- if defined?(I18n.enforce_available_locales)
22
- I18n.enforce_available_locales = true
23
- end
24
-
25
- I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
26
- I18n.load_path = Dir["#{APP_ROOT}/../i18n/server/*.yml"]
27
- I18n.default_locale = :en
28
- I18n.locale = lang.to_sym
29
-
30
- # --------------------------------------------------------- #
31
- # Options
32
- # --------------------------------------------------------- #
33
-
34
- options = {}
35
- OptionParser.new do |opts|
36
- opts.banner = "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]"
37
-
38
- opts.on("-c", "--config CONFIG", I18n.t('option.config')) do |config|
39
- options[:config] = config
40
- end
41
-
42
- opts.on("-t", "--checkconfig", I18n.t('option.checkconfig')) do |b|
43
- options[:checkconfig] = b
44
- end
45
-
46
- opts.on("-s", "--setup", I18n.t('option.setup')) do |b|
47
- options[:setup] = b
48
- end
49
-
50
- opts.on("-h", "--help", I18n.t('option.help')) do |b|
51
- puts opts
52
- exit 0
53
- end
54
- end.parse!
55
-
56
- # --------------------------------------------------------- #
57
- # Main
58
- # --------------------------------------------------------- #
59
-
60
- if options[:config].nil? or options[:config].empty?
61
- puts "#{I18n.t('option.usage')}: mpw-server -c CONFIG [options]"
62
- exit 2
63
- end
64
-
65
- server = MPW::Server.new
66
-
67
- if options[:checkconfig]
68
- server.checkconfig(options[:config])
69
- elsif options[:setup]
70
- server.setup(options[:config])
71
- else
72
- if server.checkconfig(options[:config])
73
- server.start
74
- end
75
- end
76
-
77
- server = nil
78
- exit 0
data/bin/mpw-ssh DELETED
@@ -1,89 +0,0 @@
1
- #!/usr/bin/ruby
2
- # author: nishiki
3
- # mail: nishiki@yaegashi.fr
4
- # info: a simple script who manage your passwords
5
-
6
- require 'rubygems'
7
- require 'optparse'
8
- require 'pathname'
9
- require 'locale'
10
- require 'i18n'
11
- require 'mpw/ui/clissh'
12
- require 'mpw/config'
13
-
14
- # --------------------------------------------------------- #
15
- # Set local
16
- # --------------------------------------------------------- #
17
-
18
- APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath)
19
- lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
20
-
21
- if defined?(I18n.enforce_available_locales)
22
- I18n.enforce_available_locales = true
23
- end
24
-
25
- I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
26
- I18n.load_path = Dir["#{APP_ROOT}/../i18n/cli/*.yml"]
27
- I18n.default_locale = :en
28
- I18n.locale = lang.to_sym
29
-
30
- # --------------------------------------------------------- #
31
- # Options
32
- # --------------------------------------------------------- #
33
-
34
- options = {}
35
- OptionParser.new do |opts|
36
- opts.banner = "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]"
37
-
38
- opts.on("-l", "--login LOGIN", I18n.t('ssh.option.login')) do |login|
39
- options[:login] = login
40
- end
41
-
42
- opts.on("-s", "--server SERVER", I18n.t('ssh.option.server')) do |server|
43
- options[:server] = server
44
- end
45
-
46
- opts.on("-p", "--port PORT", I18n.t('ssh.option.port')) do |port|
47
- options[:port] = port
48
- end
49
-
50
- opts.on('-c', '--config CONFIG', I18n.t('cli.option.config')) do |config|
51
- options[:config] = config
52
- end
53
-
54
- opts.on("-h", "--help", I18n.t('ssh.option.help')) do
55
- puts opts
56
- exit 0
57
- end
58
- end.parse!
59
-
60
- # --------------------------------------------------------- #
61
- # Main
62
- # --------------------------------------------------------- #
63
-
64
- config = MPW::Config.new(options[:config])
65
- check_error = config.checkconfig
66
-
67
- cli = CliSSH.new(config)
68
- cli.login = options[:login]
69
- cli.server = options[:server]
70
- cli.port = options[:port]
71
-
72
- search = ARGV[0]
73
-
74
- # Setup a new config
75
- if not check_error
76
- cli.setup(lang)
77
-
78
- elsif ARGV.length < 1
79
- puts "#{I18n.t('ssh.option.usage')}: mpw-ssh SEARCH [options]"
80
- exit 2
81
- else
82
- cli.decrypt
83
- cli.sync
84
- cli.ssh(search)
85
- end
86
-
87
- cli = nil
88
-
89
- exit 0
data/i18n/server/en.yml DELETED
@@ -1,26 +0,0 @@
1
- ---
2
- en:
3
- option:
4
- usage: "Usage"
5
- config: "Specifie the configuration file"
6
- checkconfig: "Check the configuration"
7
- setup: "Setup a new configuration file"
8
- help: "Show this message help"
9
- checkconfig:
10
- fail: "Checkconfig failed:!"
11
- empty: "ERROR: an importe option is missing!"
12
- datadir: "ERROR: le data directory doesn't exist!"
13
- form:
14
- setup:
15
- title: "Serveur configuration"
16
- host: "IP listen: "
17
- port: "Port listen: "
18
- data_dir: "Data directory: "
19
- timeout: "Timeout to second: "
20
- log_file: "Log file path: "
21
- not_valid: "ERROR: Impossible to write the configuration file!"
22
- formats:
23
- default: ! '%Y-%m-%d'
24
- long: ! '%B %d, %Y'
25
- short: ! '%b %d'
26
- custom: ! '%A, %M %B, %Y @ %l:%M%P'
data/i18n/server/fr.yml DELETED
@@ -1,26 +0,0 @@
1
- ---
2
- fr:
3
- option:
4
- usage: "Utilisation"
5
- config: "Spécifie le fichier de configuration"
6
- checkconfig: "Vérifie le fichier de configuration"
7
- setup: "Permet de générer un nouveau fichier de configuration"
8
- help: "Affiche ce message d'aide"
9
- checkconfig:
10
- fail: "Le fichier de configuration est invalide!"
11
- empty: "ERREUR: Une option importante est manquante!"
12
- datadir: "ERREUR: Le répertoire des données n'existe pas!"
13
- form:
14
- setup:
15
- title: "Configuration du serveur"
16
- host: "IP d'écoute: "
17
- port: "Port d'écoute: "
18
- data_dir: "Répertoire des données: "
19
- log_file: "Chemin du ficier de log: "
20
- timeout: "Timeout en seconde: "
21
- not_valid: "ERREUR: Impossible d'écire le fichier de configuration!"
22
- formats:
23
- default: ! '%Y-%m-%d'
24
- long: ! '%B %d, %Y'
25
- short: ! '%b %d'
26
- custom: ! '%A, %M %B, %Y @ %l:%M%P'
data/lib/mpw/server.rb DELETED
@@ -1,343 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module MPW
4
-
5
- require 'socket'
6
- require 'json'
7
- require 'highline/import'
8
- require 'digest'
9
- require 'logger'
10
-
11
-
12
- class Server
13
-
14
- attr_accessor :error_msg
15
-
16
- # Constructor
17
- def initialize
18
- YAML::ENGINE.yamler='syck'
19
- end
20
-
21
- # Start the server
22
- def start
23
- server = TCPServer.open(@host, @port)
24
- @log.info("The server is started on #{@host}:#{@port}")
25
-
26
- loop do
27
- Thread.start(server.accept) do |client|
28
- @log.info("#{client.peeraddr[3]} is connected")
29
-
30
- while true do
31
- msg = get_client_msg(client)
32
-
33
- next if not msg
34
-
35
- if msg['gpg_key'].nil? or msg['gpg_key'].empty? or msg['password'].nil? or msg['password'].empty?
36
- @log.warning("#{client.peeraddr[3]} is disconnected because no password or no gpg_key")
37
- close_connection(client)
38
- next
39
- end
40
-
41
- case msg['action']
42
- when 'get'
43
- @log.debug("#{client.peeraddr[3]} GET gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}")
44
- client.puts get_file(msg)
45
- when 'update'
46
- @log.debug("#{client.peeraddr[3]} UPDATE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}")
47
- client.puts update_file(msg)
48
- when 'delete'
49
- @log.debug("#{client.peeraddr[3]} DELETE gpg_key=#{msg['gpg_key']} suffix=#{msg['suffix']}")
50
- client.puts delete_file(msg)
51
- else
52
- @log.warning("#{client.peeraddr[3]} is disconnected because unkwnow command")
53
- send_msg = {action: 'unknown',
54
- gpg_key: msg['gpg_key'],
55
- error: 'server.error.client.unknown'
56
- }
57
- client.puts send_msg
58
- close_connection(client)
59
- end
60
- end
61
- end
62
- end
63
-
64
- rescue Exception => e
65
- puts "Impossible to start the server: #{e}"
66
- @log.error("Impossible to start the server: #{e}")
67
- exit 2
68
- end
69
-
70
- # Get a gpg file
71
- # @args: msg -> message puts by the client
72
- # @rtrn: json message
73
- def get_file(msg)
74
- gpg_key = msg['gpg_key'].sub('@', '_')
75
-
76
- if msg['suffix'].nil? or msg['suffix'].empty?
77
- file_gpg = "#{@data_dir}/#{gpg_key}.yml"
78
- else
79
- file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml"
80
- end
81
-
82
- if File.exist?(file_gpg)
83
- gpg_data = YAML::load_file(file_gpg)
84
- salt = gpg_data['gpg']['salt']
85
- hash = gpg_data['gpg']['hash']
86
- data = gpg_data['gpg']['data']
87
-
88
- if is_authorized?(msg['password'], salt, hash)
89
- send_msg = {action: 'get',
90
- gpg_key: msg['gpg_key'],
91
- data: data,
92
- error: nil
93
- }
94
- else
95
- send_msg = {action: 'get',
96
- gpg_key: msg['gpg_key'],
97
- error: 'server.error.client.no_authorized'
98
- }
99
- end
100
- else
101
- send_msg = {action: 'get',
102
- gpg_key: msg['gpg_key'],
103
- data: '',
104
- error: nil
105
- }
106
- end
107
-
108
- return send_msg.to_json
109
- end
110
-
111
- # Update a file
112
- # @args: msg -> message puts by the client
113
- # @rtrn: json message
114
- def update_file(msg)
115
- gpg_key = msg['gpg_key'].sub('@', '_')
116
- data = msg['data']
117
-
118
- if data.nil? or data.empty?
119
- send_msg = {action: 'update',
120
- gpg_key: msg['gpg_key'],
121
- error: 'server.error.client.no_data'
122
- }
123
-
124
- return send_msg.to_json
125
- end
126
-
127
- if msg['suffix'].nil? or msg['suffix'].empty?
128
- file_gpg = "#{@data_dir}/#{gpg_key}.yml"
129
- else
130
- file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml"
131
- end
132
-
133
- if File.exist?(file_gpg)
134
- gpg_data = YAML::load_file(file_gpg)
135
- salt = gpg_data['gpg']['salt']
136
- hash = gpg_data['gpg']['hash']
137
-
138
- else
139
- salt = generate_salt
140
- hash = Digest::SHA256.hexdigest(salt + msg['password'])
141
- end
142
-
143
- if is_authorized?(msg['password'], salt, hash)
144
- begin
145
- config = {'gpg' => {'salt' => salt,
146
- 'hash' => hash,
147
- 'data' => data
148
- }
149
- }
150
-
151
- File.open(file_gpg, 'w+') do |file|
152
- file << config.to_yaml
153
- end
154
-
155
- send_msg = {action: 'update',
156
- gpg_key: msg['gpg_key'],
157
- error: nil
158
- }
159
- rescue Exception => e
160
- send_msg = {action: 'update',
161
- gpg_key: msg['gpg_key'],
162
- error: 'server.error.client.unknown'
163
- }
164
- end
165
- else
166
- send_msg = {action: 'update',
167
- gpg_key: msg['gpg_key'],
168
- error: 'server.error.client.no_authorized'
169
- }
170
- end
171
-
172
- return send_msg.to_json
173
- end
174
-
175
- # Remove a gpg file
176
- # @args: msg -> message puts by the client
177
- # @rtrn: json message
178
- def delete_file(msg)
179
- gpg_key = msg['gpg_key'].sub('@', '_')
180
-
181
- if msg['suffix'].nil? or msg['suffix'].empty?
182
- file_gpg = "#{@data_dir}/#{gpg_key}.yml"
183
- else
184
- file_gpg = "#{@data_dir}/#{gpg_key}-#{msg['suffix']}.yml"
185
- end
186
-
187
- if not File.exist?(file_gpg)
188
- send_msg = {:action => 'delete',
189
- :gpg_key => msg['gpg_key'],
190
- :error => nil
191
- }
192
-
193
- return send_msg.to_json
194
- end
195
-
196
- gpg_data = YAML::load_file(file_gpg)
197
- salt = gpg_data['gpg']['salt']
198
- hash = gpg_data['gpg']['hash']
199
-
200
- if is_authorized?(msg['password'], salt, hash)
201
- begin
202
- File.unlink(file_gpg)
203
-
204
- send_msg = {action: 'delete',
205
- gpg_key: msg['gpg_key'],
206
- error: nil
207
- }
208
- rescue Exception => e
209
- send_msg = {action: 'delete',
210
- gpg_key: msg['gpg_key'],
211
- error: 'server.error.client.unknown'
212
- }
213
- end
214
- else
215
- send_msg = {action: 'delete',
216
- gpg_key: msg['gpg_key'],
217
- error: 'server.error.client.no_authorized'
218
- }
219
- end
220
-
221
- return send_msg.to_json
222
- end
223
-
224
- # Check is the hash equal the password with the salt
225
- # @args: password -> the user password
226
- # salt -> the salt
227
- # hash -> the hash of the password with the salt
228
- # @rtrn: true is is good, else false
229
- def is_authorized?(password, salt, hash)
230
- if hash == Digest::SHA256.hexdigest(salt + password)
231
- return true
232
- else
233
- return false
234
- end
235
- end
236
-
237
- # Get message to client
238
- # @args: client -> client connection
239
- # @rtrn: array of the json string, or false if isn't json message
240
- def get_client_msg(client)
241
- msg = client.gets
242
- return JSON.parse(msg)
243
- rescue
244
- closeConnection(client)
245
- return false
246
- end
247
-
248
- # Close the client connection
249
- # @args: client -> client connection
250
- def close_connection(client)
251
- client.puts "Closing the connection. Bye!"
252
- client.close
253
- end
254
-
255
- # Check the config file
256
- # @args: file_config -> the configuration file
257
- # @rtrn: true if the config file is correct
258
- def checkconfig(file_config)
259
- config = YAML::load_file(file_config)
260
- @host = config['config']['host']
261
- @port = config['config']['port'].to_i
262
- @data_dir = config['config']['data_dir']
263
- @log_file = config['config']['log_file']
264
- @timeout = config['config']['timeout'].to_i
265
-
266
- if @host.empty? or @port <= 0 or @data_dir.empty?
267
- puts I18n.t('checkconfig.fail')
268
- puts I18n.t('checkconfig.empty')
269
- return false
270
- end
271
-
272
- if not Dir.exist?(@data_dir)
273
- puts I18n.t('checkconfig.fail')
274
- puts I18n.t('checkconfig.datadir')
275
- return false
276
- end
277
-
278
- if @log_file.nil? or @log_file.empty?
279
- puts I18n.t('checkconfig.fail')
280
- puts I18n.t('checkconfig.log_file_empty')
281
- return false
282
- else
283
- begin
284
- @log = Logger.new(@log_file)
285
- rescue
286
- puts I18n.t('checkconfig.fail')
287
- puts I18n.t('checkconfig.log_file_create')
288
- return false
289
- end
290
- end
291
-
292
- return true
293
- rescue Exception => e
294
- puts "#{I18n.t('checkconfig.fail')}\n#{e}"
295
- return false
296
- end
297
-
298
- # Create a new config file
299
- # @args: file_config -> the configuration file
300
- # @rtrn: true if le config file is create
301
- def setup(file_config)
302
- puts I18n.t('form.setup.title')
303
- puts '--------------------'
304
- host = ask(I18n.t('form.setup.host')).to_s
305
- port = ask(I18n.t('form.setup.port')).to_s
306
- data_dir = ask(I18n.t('form.setup.data_dir')).to_s
307
- log_file = ask(I18n.t('form.setup.log_file')).to_s
308
- timeout = ask(I18n.t('form.setup.timeout')).to_s
309
-
310
- config = {'config' => {'host' => host,
311
- 'port' => port,
312
- 'data_dir' => data_dir,
313
- 'log_file' => log_file,
314
- 'timeout' => timeout
315
- }
316
- }
317
-
318
- File.open(file_config, 'w') do |file|
319
- file << config.to_yaml
320
- end
321
-
322
- return true
323
- rescue Exception => e
324
- puts "#{I18n.t('form.setup.not_valid')}\n#{e}"
325
- return false
326
- end
327
-
328
- # Generate a random salt
329
- # @args: length -> the length salt
330
- # @rtrn: a random string
331
- def generate_salt(length=4)
332
- if length.to_i <= 0 or length.to_i > 16
333
- length = 4
334
- else
335
- length = length.to_i
336
- end
337
-
338
- return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(length).join
339
- end
340
-
341
- end
342
-
343
- end
data/lib/mpw/sync/mpw.rb DELETED
@@ -1,124 +0,0 @@
1
- #!/usr/bin/ruby
2
- # author: nishiki
3
-
4
- require 'rubygems'
5
- require 'i18n'
6
- require 'socket'
7
- require 'json'
8
- require 'timeout'
9
-
10
- module MPW
11
- class SyncMPW
12
-
13
- attr_accessor :error_msg
14
- attr_accessor :enable
15
-
16
- # Constructor
17
- # @args: host -> the server host
18
- # port -> ther connection port
19
- # gpg_key -> the gpg key
20
- # password -> the remote password
21
- # suffix -> the suffix file
22
- def initialize(host, user, password, suffix, port=nil)
23
- @error_msg = nil
24
- @enable = false
25
-
26
- @host = host
27
- @port = !port.instance_of?(Integer) ? 2201 : port
28
- @gpg_key = user
29
- @password = password
30
- @suffix = suffix
31
- end
32
-
33
- # Connect to server
34
- # @rtrn: false if the connection fail
35
- def connect
36
- Timeout.timeout(10) do
37
- begin
38
- TCPSocket.open(@host, @port) do
39
- @enable = true
40
- end
41
- rescue Errno::ENETUNREACH
42
- retry
43
- end
44
- end
45
- rescue Timeout::Error
46
- @error_msg = "#{I18n.t('error.timeout')}\n#{e}"
47
- @enable = false
48
- rescue Exception => e
49
- @error_msg = "#{I18n.t('error.sync.connection')}\n#{e}"
50
- @enable = false
51
- else
52
- return @enable
53
- end
54
-
55
- # Get data on server
56
- # @args: gpg_password -> the gpg password
57
- # @rtrn: nil if nothing data or error
58
- def get(file_tmp)
59
- return false if not @enable
60
-
61
- msg = nil
62
- TCPSocket.open(@host, @port) do |socket|
63
- send_msg = {action: 'get',
64
- gpg_key: @gpg_key,
65
- password: @password,
66
- suffix: @suffix
67
- }
68
-
69
- socket.puts send_msg.to_json
70
- msg = JSON.parse(socket.gets)
71
- end
72
-
73
- if not defined?(msg['error'])
74
- @error_msg = I18n.t('error.sync.communication')
75
- return false
76
- elsif not msg['error'].nil?
77
- @error_msg = I18n.t(msg['error'])
78
- return false
79
- end
80
-
81
- File.open(file_tmp, 'w') do |file|
82
- file << msg['data']
83
- end
84
-
85
- return true
86
- rescue Exception => e
87
- @error_msg = "#{I18n.t('error.sync.download')}\n#{e}"
88
- return false
89
- end
90
-
91
- # Update the remote data
92
- # @args: data -> the data to send on server
93
- # @rtrn: false if there is a problem
94
- def update(file_gpg)
95
- return true if not @enable
96
-
97
- data = File.open(file_gpg, 'r').read
98
-
99
- msg = nil
100
- TCPSocket.open(@host, @port) do |socket|
101
- send_msg = {action: 'update',
102
- gpg_key: @gpg_key,
103
- password: @password,
104
- suffix: @suffix,
105
- data: data
106
- }
107
-
108
- socket.puts send_msg.to_json
109
- msg = JSON.parse(socket.gets)
110
- end
111
-
112
- if not defined?(msg['error'])
113
- @error_msg = I18n.t('error.sync.communication')
114
- return false
115
- elsif msg['error'].nil?
116
- return true
117
- else
118
- @error_msg = I18n.t(msg['error'])
119
- return false
120
- end
121
- end
122
-
123
- end
124
- end