rubeepass 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c9173d805e33e51cc75649bf98888fe43d1ddf6
4
- data.tar.gz: cf33596494c2237f9d155b0b3b19695159e04e66
3
+ metadata.gz: 27da21673c45cfb2ab29bb1c984f477ea16036d6
4
+ data.tar.gz: 3785cf861668b77aea2d275248f4747e85425c2a
5
5
  SHA512:
6
- metadata.gz: e17d97fee36dec9b46bb7cee8012ceab4cad86f1efab7e5f391597d4b057d4d99bd218a4ff5683474aaba78af0a915f9f3b5ed589bcd424a5cb7c897763fff18
7
- data.tar.gz: ce56faf8900c3425e55fd480966ee5e39a73fc886eda135156a54c52e2e9f8e08726dd84f695755e911a0aa96fc75f8feff2bb7d83d05f2f5328bd50a98fb951
6
+ metadata.gz: 301723a1764cb1f6698e912069e39fb65f1577dd94ad0dbe3e4ed329c495f6bb3110ceea15e0ce6c1ac56bc91ef1758a642742c9d35ce8857d9368f29b79890e
7
+ data.tar.gz: 9edb83c2c117297bd7d731fd610fb81c7606fa9ded5d0deefe046f24408d6652bc99547aa560c41fb027225707f912bd610c72f84c187901e9c19e3bdac4b71a
data/bin/rpass CHANGED
@@ -3,37 +3,57 @@
3
3
  require "colorize"
4
4
  require "djinni"
5
5
  require "io/console"
6
- require "json"
6
+ require "json_config"
7
7
  require "optparse"
8
- require "pathname"
9
8
  require "rubeepass"
10
9
 
11
- class RPassExit
10
+ class RubeePassExit
12
11
  GOOD = 0
13
12
  INVALID_OPTION = 1
14
13
  INVALID_ARGUMENT = 2
15
14
  MISSING_ARGUMENT = 3
16
15
  EXTRA_ARGUMENTS = 4
17
- KDBX_NOT_FOUND = 5
18
- KDBX_NOT_READABLE = 6
19
- KEYFILE_NOT_FOUND = 7
20
- KEYFILE_NOT_READABLE = 8
21
- KDBX_NOT_OPENED = 9
16
+ EXCEPTION = 5
17
+ end
18
+
19
+ class RubeePassConfig < JSONConfig
20
+ def default_config
21
+ set("last_kdbx", nil)
22
+ set("last_keyfile", nil)
23
+ set("timeout", 10)
24
+ end
25
+
26
+ def last_kdbx(kdbx = nil)
27
+ set("last_kdbx", kdbx.to_s) if (kdbx)
28
+ kdbx = get("last_kdbx")
29
+ return nil if (kdbx.nil? || kdbx.empty?)
30
+ return kdbx
31
+ end
32
+
33
+ def last_keyfile(keyfile = nil)
34
+ set("last_keyfile", keyfile.to_s) if (keyfile)
35
+ keyfile = get("last_keyfile")
36
+ return nil if (keyfile.nil? || keyfile.empty?)
37
+ return keyfile
38
+ end
39
+
40
+ def timeout(t = nil)
41
+ set("timeout", t) if (t)
42
+ t = get("timeout")
43
+ case t
44
+ when /[0-9]+/
45
+ return t.to_i
46
+ else
47
+ return nil
48
+ end
49
+ end
22
50
  end
23
51
 
24
52
  def get_password
25
53
  print "Enter password: "
26
- begin
27
- passwd = STDIN.noecho(&:gets)
28
- puts
29
- return passwd.chomp
30
- rescue Interrupt => e
31
- puts
32
- exit RPassExit::GOOD
33
- rescue
34
- puts
35
- exit RPassExit::KDBX_NOT_OPENED
36
- end
54
+ passwd = STDIN.noecho(&:gets)
55
+ puts
56
+ return passwd.chomp
37
57
  end
38
58
 
39
59
  def parse(args)
@@ -44,6 +64,7 @@ def parse(args)
44
64
  options["password"] = nil
45
65
  options["keyfile"] = nil
46
66
  options["timeout"] = nil
67
+ options["verbose"] = false
47
68
 
48
69
  parser = OptionParser.new do |opts|
49
70
  opts.banner = "Usage: #{File.basename($0)} [OPTIONS] [kdbx]"
@@ -75,7 +96,7 @@ def parse(args)
75
96
 
76
97
  opts.on("-h", "--help", "Display this help message") do
77
98
  puts opts
78
- exit RPassExit::GOOD
99
+ exit RubeePassExit::GOOD
79
100
  end
80
101
 
81
102
  opts.on(
@@ -83,7 +104,11 @@ def parse(args)
83
104
  "--keyfile=KEYFILE",
84
105
  "Use specified keyfile"
85
106
  ) do |keyfile|
86
- options["keyfile"] = Pathname.new(keyfile).expand_path
107
+ options["keyfile"] = keyfile
108
+ end
109
+
110
+ opts.on("--nocolor", "Disable colorized output") do
111
+ String.disable_colorization = true
87
112
  end
88
113
 
89
114
  opts.on(
@@ -98,11 +123,19 @@ def parse(args)
98
123
  options["timeout"] = t.to_i
99
124
  end
100
125
 
126
+ opts.on(
127
+ "-v",
128
+ "--verbose",
129
+ "Show backtrace when error occurs"
130
+ ) do
131
+ options["verbose"] = true
132
+ end
133
+
101
134
  opts.on(
102
135
  "",
103
136
  "FORMATS",
104
- "\tgzip",
105
- "\txml"
137
+ " gzip",
138
+ " xml"
106
139
  )
107
140
  end
108
141
 
@@ -111,109 +144,63 @@ def parse(args)
111
144
  rescue OptionParser::InvalidOption => e
112
145
  puts e.message
113
146
  puts parser
114
- exit RPassExit::INVALID_OPTION
147
+ exit RubeePassExit::INVALID_OPTION
115
148
  rescue OptionParser::InvalidArgument => e
116
149
  puts e.message
117
150
  puts parser
118
- exit RPassExit::INVALID_ARGUMENT
151
+ exit RubeePassExit::INVALID_ARGUMENT
119
152
  rescue OptionParser::MissingArgument => e
120
153
  puts e.message
121
154
  puts parser
122
- exit RPassExit::MISSING_ARGUMENT
155
+ exit RubeePassExit::MISSING_ARGUMENT
123
156
  end
124
157
 
125
158
  if (args.length > 1)
126
159
  puts parser
127
- exit RPassExit::EXTRA_ARGUMENTS
160
+ exit RubeePassExit::EXTRA_ARGUMENTS
128
161
  end
129
162
 
130
163
  # Read config
131
- rc = read_rpassrc
164
+ rc = RubeePassConfig.new("~/.rpassrc")
132
165
 
133
166
  # Determine kdbx and keyfile
134
167
  if (args.length == 1)
135
168
  # Use specified kdbx (and keyfile if specified)
136
- options["kdbx"] = Pathname.new(args[0]).expand_path
169
+ options["kdbx"] = args[0]
137
170
  else
138
171
  # Use kdbx from config if stored
139
- if (rc["last_kdbx"] && !rc["last_kdbx"].empty?)
140
- options["kdbx"] = Pathname.new(
141
- rc["last_kdbx"]
142
- ).expand_path
172
+ if (rc.last_kdbx)
173
+ options["kdbx"] = rc.last_kdbx
143
174
  end
144
175
 
145
176
  # Use keyfile from config if stored and not specified already
146
177
  if (options["keyfile"].nil?)
147
- if (rc["last_keyfile"] && !rc["last_keyfile"].empty?)
148
- options["keyfile"] = Pathname.new(
149
- rc["last_keyfile"]
150
- ).expand_path
178
+ if (rc.last_keyfile)
179
+ options["keyfile"] = rc.last_keyfile
151
180
  end
152
181
  end
153
182
  end
154
183
 
155
184
  # Determine timeout
156
185
  if (options["timeout"].nil?)
157
- if (rc["timeout"])
158
- options["timeout"] = rc["timeout"]
159
- else
160
- options["timeout"] = 7
161
- end
186
+ options["timeout"] = 10
187
+ options["timeout"] = rc.timeout if (rc.timeout)
162
188
  end
163
189
 
164
190
  # Throw error if kdbx not specified or in config
165
191
  if (options["kdbx"].nil?)
166
192
  puts parser
167
- exit RPassExit::MISSING_ARGUMENT
168
- end
169
-
170
- # Throw error if kdbx does not exist or is not readable
171
- if (!options["kdbx"].exist?)
172
- puts parser
173
- exit RPassExit::KDBX_NOT_FOUND
174
- elsif (!options["kdbx"].readable?)
175
- puts parser
176
- exit RPassExit::KDBX_NOT_READABLE
177
- end
178
-
179
- # Throw error if keyfile does not exist or is not readable
180
- if (options["keyfile"])
181
- if (!options["keyfile"].exist?)
182
- puts parser
183
- exit RPassExit::KEYFILE_NOT_FOUND
184
- elsif (!options["keyfile"].readable?)
185
- puts parser
186
- exit RPassExit::KEYFILE_NOT_READABLE
187
- end
193
+ exit RubeePassExit::MISSING_ARGUMENT
188
194
  end
189
195
 
190
196
  # Store data in config
191
- rc["last_kdbx"] = options["kdbx"]
192
- rc["last_keyfile"] = options["keyfile"]
193
- rc["timeout"] = options["timeout"]
194
- write_rpassrc(rc)
197
+ rc.last_kdbx(options["kdbx"])
198
+ rc.last_keyfile(options["keyfile"])
199
+ rc.timeout(options["timeout"])
195
200
 
196
201
  return options
197
202
  end
198
203
 
199
- def read_rpassrc
200
- default = Hash.new
201
- default["last_kdbx"] = nil
202
- default["last_keyfile"] = nil
203
- default["timeout"] = 7
204
-
205
- rc_file = Pathname.new("~/.rpassrc").expand_path
206
- return default if (!rc_file.exist? && !rc_file.symlink?)
207
- return JSON.parse(File.read(rc_file))
208
- end
209
-
210
- def write_rpassrc(rc)
211
- rc_file = Pathname.new("~/.rpassrc").expand_path
212
- File.open(rc_file, "w") do |f|
213
- f.write(JSON.pretty_generate(rc))
214
- end
215
- end
216
-
217
204
  options = parse(ARGV)
218
205
 
219
206
  kdbx = options["kdbx"]
@@ -221,39 +208,41 @@ password = options["password"] if (options["password"])
221
208
  password = get_password if (options["password"].nil?)
222
209
  keyfile = options["keyfile"]
223
210
 
224
- keepass = RubeePass.new(kdbx, password, keyfile)
225
-
226
- if (options["export_file"])
227
- begin
228
- keepass.export(
229
- options["export_file"],
230
- options["export_format"]
231
- )
232
- rescue RubeePass::Error::InvalidPasswordError => e
233
- puts e.message
234
- password = get_password
235
- keepass = RubeePass.new(kdbx, password, keyfile)
211
+ begin
212
+ keepass = RubeePass.new(
213
+ kdbx,
214
+ password,
215
+ keyfile,
216
+ !String.disable_colorization
217
+ )
218
+
219
+ loop do
220
+ begin
221
+ if (options["export_file"])
222
+ keepass.export(
223
+ options["export_file"],
224
+ options["export_format"]
225
+ )
226
+ exit RubeePassExit::GOOD
227
+ else
228
+ keepass.open
229
+ end
230
+ break
231
+ rescue RubeePass::Error::InvalidPassword => e
232
+ puts e.message
233
+ password = get_password
234
+ keepass = RubeePass.new(
235
+ kdbx,
236
+ password,
237
+ keyfile,
238
+ !String.disable_colorization
239
+ )
240
+ end
236
241
  end
237
- exit RPassExit::GOOD
238
- end
239
242
 
240
- loop do
241
- begin
242
- keepass.open
243
- break
244
- rescue RubeePass::Error::InvalidPasswordError => e
245
- puts e.message
246
- password = get_password
247
- keepass = RubeePass.new(kdbx, password, keyfile)
248
- rescue RubeePass::Error => e
249
- puts e.message
250
- exit RPassExit::KDBX_NOT_OPENED
251
- end
252
- end
243
+ djinni = Djinni.new
244
+ djinni.load_wishes("#{File.dirname(__FILE__)}/../lib/rubeepass/wish")
253
245
 
254
- djinni = Djinni.new
255
- djinni.load_wishes("#{File.dirname(__FILE__)}/../lib/rubeepass/wish")
256
- begin
257
246
  if (options["command"])
258
247
  djinni.grant_wish(
259
248
  "#{options["command"].chomp}\n",
@@ -269,14 +258,44 @@ begin
269
258
  {
270
259
  "keepass" => keepass,
271
260
  "cwd" => keepass.db,
272
- "clipboard_timeout" => options["timeout"]
261
+ "clipboard_timeout" => options["timeout"],
262
+ "prompt_color" => "light_white"
273
263
  },
274
- "rpass:/> ".white
264
+ "rpass:/> ".light_white
275
265
  )
276
266
  end
277
- # rescue SystemExit => e
267
+ rescue SystemExit
268
+ # Quit from djinni
269
+ # Exit gracefully
270
+ rescue Interrupt
271
+ # ^C
272
+ # Exit gracefully
273
+ rescue Errno::EPIPE
274
+ # Do nothing. This can happen if piping to another program such as
275
+ # less. Usually if less is closed before we're done with STDOUT.
276
+ rescue RubeePass::Error => e
277
+ puts e.message
278
+ exit RubeePassExit::EXCEPTION
279
+ rescue Exception => e
280
+ $stderr.puts "Oops! Looks like an error has occured! If the " \
281
+ "error persists, file a bug at:".word_wrap
282
+ $stderr.puts
283
+ $stderr.puts " https://gitlab.com/mjwhitta/rubeepass/issues"
284
+ $stderr.puts
285
+ $stderr.puts "Maybe the message below will help. If not, you " \
286
+ "can use the --verbose flag to get a backtrace.".word_wrap
287
+
288
+ $stderr.puts e.message.white.on_red
289
+ if (options["verbose"])
290
+ e.backtrace.each do |line|
291
+ $stderr.puts line.light_yellow
292
+ end
293
+ end
294
+ exit RubeePassExit::EXCEPTION
278
295
  ensure
279
- keepass.clear_clipboard
280
- keepass.wait_to_exit
296
+ if (keepass)
297
+ keepass.clear_clipboard
298
+ keepass.wait_to_exit
299
+ end
281
300
  end
282
- exit RPassExit::GOOD
301
+ exit RubeePassExit::GOOD
@@ -22,14 +22,30 @@ class RubeePass::Entry
22
22
  return (self.title.downcase <=> other.title.downcase)
23
23
  end
24
24
 
25
+ def colorize_password(passwd)
26
+ return passwd if (!@colorize)
27
+ return passwd.light_red
28
+ end
29
+ private :colorize_password
30
+
31
+ def colorize_title(title)
32
+ return title if (!@colorize)
33
+ return title.light_green
34
+ end
35
+ private :colorize_title
36
+
25
37
  def details(level = 0, show_passwd = false)
26
38
  lvl = Array.new(level, " ").join
27
39
 
28
40
  ret = Array.new
29
- ret.push("#{lvl}Title : #{@title}".green)
41
+ ret.push(colorize_title("#{lvl}Title : #{@title}"))
30
42
  # ret.push("#{lvl}UUID : #{@uuid}")
31
43
  ret.push("#{lvl}Username : #{@username}")
32
- ret.push("#{lvl}Password : #{password}".red) if (show_passwd)
44
+ if (show_passwd)
45
+ ret.push(
46
+ colorize_password("#{lvl}Password : #{password}")
47
+ )
48
+ end
33
49
  ret.push("#{lvl}Url : #{@url}")
34
50
 
35
51
  first = true
@@ -45,7 +61,7 @@ class RubeePass::Entry
45
61
  return ret.join("\n")
46
62
  end
47
63
 
48
- def self.from_xml(keepass, parent, xml)
64
+ def self.from_xml(keepass, parent, xml, colorize = false)
49
65
  notes = ""
50
66
  password = ""
51
67
  title = ""
@@ -95,7 +111,8 @@ class RubeePass::Entry
95
111
  title,
96
112
  url,
97
113
  username,
98
- uuid
114
+ uuid,
115
+ colorize
99
116
  )
100
117
  end
101
118
 
@@ -105,9 +122,9 @@ class RubeePass::Entry
105
122
  begin
106
123
  data = base64.unpack("m*")[0].fix
107
124
  rescue ArgumentError => e
108
- raise Error::InvalidProtectedDataError.new
125
+ raise Error::InvalidProtectedData.new
109
126
  end
110
- raise Error::InvalidProtectedDataError.new if (data.nil?)
127
+ raise Error::InvalidProtectedData.new if (data.nil?)
111
128
 
112
129
  return keepass.protected_decryptor.add_to_stream(data)
113
130
  end
@@ -120,8 +137,10 @@ class RubeePass::Entry
120
137
  title,
121
138
  url,
122
139
  username,
123
- uuid
140
+ uuid,
141
+ colorize = false
124
142
  )
143
+ @colorize = colorize
125
144
  @group = group
126
145
  @keepass = keepass
127
146
  @notes = notes
@@ -0,0 +1,5 @@
1
+ class RubeePass::Error::FileNotFound < RubeePass::Error
2
+ def initialize(file)
3
+ super("File not found: #{file}")
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RubeePass::Error::FileNotReadable < RubeePass::Error
2
+ def initialize(file)
3
+ super("File not readable: #{file}")
4
+ end
5
+ end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidGzipError < RubeePass::Error
3
+ class RubeePass::Error::InvalidGzip < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid gzip format!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidHeaderError < RubeePass::Error
3
+ class RubeePass::Error::InvalidHeader < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid header format!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidMagicError < RubeePass::Error
3
+ class RubeePass::Error::InvalidMagic < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid magic values detected!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidPasswordError < RubeePass::Error
3
+ class RubeePass::Error::InvalidPassword < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid password provided!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidProtectedDataError < RubeePass::Error
3
+ class RubeePass::Error::InvalidProtectedData < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid protected data!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidProtectedStreamKeyError < RubeePass::Error
3
+ class RubeePass::Error::InvalidProtectedStreamKey < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid protected stream key!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidVersionError < RubeePass::Error
3
+ class RubeePass::Error::InvalidVersion < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid version detected!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidXMLError < RubeePass::Error
3
+ class RubeePass::Error::InvalidXML < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid xml schema!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::NotAESError < RubeePass::Error
3
+ class RubeePass::Error::NotAES < RubeePass::Error
4
4
  def initialize
5
5
  super("Not AES!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::NotSalsa20Error < RubeePass::Error
3
+ class RubeePass::Error::NotSalsa20 < RubeePass::Error
4
4
  def initialize
5
5
  super("Not a Salsa20 CrsAlgorithm!")
6
6
  end
@@ -1,13 +1,15 @@
1
1
  class RubeePass::Error < RuntimeError
2
2
  end
3
3
 
4
- require "rubeepass/error/invalid_gzip_error"
5
- require "rubeepass/error/invalid_header_error"
6
- require "rubeepass/error/invalid_magic_error"
7
- require "rubeepass/error/invalid_password_error"
8
- require "rubeepass/error/invalid_protected_data_error"
9
- require "rubeepass/error/invalid_protected_stream_key_error"
10
- require "rubeepass/error/invalid_version_error"
11
- require "rubeepass/error/invalid_xml_error"
12
- require "rubeepass/error/not_aes_error"
13
- require "rubeepass/error/not_salsa20_error"
4
+ require "rubeepass/error/file_not_found"
5
+ require "rubeepass/error/file_not_readable"
6
+ require "rubeepass/error/invalid_gzip"
7
+ require "rubeepass/error/invalid_header"
8
+ require "rubeepass/error/invalid_magic"
9
+ require "rubeepass/error/invalid_password"
10
+ require "rubeepass/error/invalid_protected_data"
11
+ require "rubeepass/error/invalid_protected_stream_key"
12
+ require "rubeepass/error/invalid_version"
13
+ require "rubeepass/error/invalid_xml"
14
+ require "rubeepass/error/not_aes"
15
+ require "rubeepass/error/not_salsa20"
@@ -20,12 +20,18 @@ class RubeePass::Group
20
20
  return (self.name.downcase <=> other.name.downcase)
21
21
  end
22
22
 
23
+ def colorize_header(header)
24
+ return header if (!@colorize)
25
+ return header.light_blue
26
+ end
27
+ private :colorize_header
28
+
23
29
  def details(level = 0, show_passwd = false)
24
30
  out = Array.new
25
31
  lvl = Array.new(level, " ").join
26
32
 
27
- group_details = [ "#{@path}".blue ] if (level == 0)
28
- group_details = [ "#{@name}".blue ] if (level != 0)
33
+ group_details = [ colorize_header(@path) ] if (level == 0)
34
+ group_details = [ colorize_header(@name) ] if (level != 0)
29
35
 
30
36
  group_details.each do |line|
31
37
  out.push("#{lvl}#{line}")
@@ -64,7 +70,7 @@ class RubeePass::Group
64
70
  return cwd
65
71
  end
66
72
 
67
- def self.from_xml(keepass, parent, xml)
73
+ def self.from_xml(keepass, parent, xml, colorize = false)
68
74
  name = xml.elements["Name"].text if (parent)
69
75
  name = "" if (name.nil?)
70
76
  name = "/" if (parent.nil?)
@@ -82,7 +88,8 @@ class RubeePass::Group
82
88
  keepass,
83
89
  name,
84
90
  notes,
85
- uuid
91
+ uuid,
92
+ colorize
86
93
  )
87
94
 
88
95
  if (xml.elements["Entry"])
@@ -90,7 +97,8 @@ class RubeePass::Group
90
97
  entry = RubeePass::Entry.from_xml(
91
98
  keepass,
92
99
  group,
93
- entry_xml
100
+ entry_xml,
101
+ colorize
94
102
  )
95
103
  group.entries[entry.title] = entry
96
104
  end
@@ -101,7 +109,8 @@ class RubeePass::Group
101
109
  child = RubeePass::Group.from_xml(
102
110
  keepass,
103
111
  group,
104
- group_xml
112
+ group_xml,
113
+ colorize
105
114
  )
106
115
  group.groups[child.name] = child
107
116
  end
@@ -161,7 +170,15 @@ class RubeePass::Group
161
170
  return false
162
171
  end
163
172
 
164
- def initialize(group, keepass, name, notes, uuid)
173
+ def initialize(
174
+ group,
175
+ keepass,
176
+ name,
177
+ notes,
178
+ uuid,
179
+ colorize = false
180
+ )
181
+ @colorize = colorize
165
182
  @entries = Hash.new
166
183
  @group = group
167
184
  @groups = Hash.new
@@ -13,13 +13,18 @@ class CDWish < Djinni::Wish
13
13
  def execute(args, djinni_env = {})
14
14
  keepass = djinni_env["keepass"]
15
15
  cwd = djinni_env["cwd"]
16
+ prompt_color = djinni_env["prompt_color"]
16
17
 
17
18
  args = keepass.absolute_path(args, cwd.path)
18
19
  new_cwd = keepass.find_group(args)
19
20
 
20
21
  if (new_cwd)
21
22
  djinni_env["cwd"] = new_cwd
22
- prompt = "rpass:#{new_cwd.name}> ".white
23
+ if (prompt_color)
24
+ prompt = "rpass:#{new_cwd.name}> ".send(prompt_color)
25
+ else
26
+ prompt = "rpass:#{new_cwd.name}> "
27
+ end
23
28
  djinni_env["djinni_prompt"] = prompt
24
29
  else
25
30
  puts "Group \"#{args}\" doesn't exist!"
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class CopyWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class EchoWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class LSWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class ShowAllWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class ShowWish < Djinni::Wish
data/lib/rubeepass.rb CHANGED
@@ -2,6 +2,7 @@ require "cgi"
2
2
  require "digest"
3
3
  require "openssl"
4
4
  require "os"
5
+ require "pathname"
5
6
  require "rexml/document"
6
7
  require "scoobydoo"
7
8
  require "shellwords"
@@ -173,10 +174,28 @@ class RubeePass
173
174
  return @db.fuzzy_find(input)
174
175
  end
175
176
 
176
- def initialize(kdbx, password, keyfile = nil)
177
- @kdbx = kdbx
178
- @keyfile = keyfile
177
+ def initialize(kdbx, password, keyfile = nil, colorize = false)
178
+ @colorize = colorize
179
+ @kdbx = Pathname.new(kdbx).expand_path
180
+ @keyfile = nil
181
+ @keyfile = Pathname.new(keyfile).expand_path if (keyfile)
179
182
  @password = password
183
+
184
+ if (@kdbx.nil?)
185
+ # TODO
186
+ elsif (!@kdbx.exist?)
187
+ raise RubeePass::Error::FileNotFound.new(@kdbx)
188
+ elsif (!@kdbx.readable?)
189
+ raise RubeePass::Error::FileNotReadable.new(@kdbx)
190
+ end
191
+
192
+ if (@keyfile)
193
+ if (!@keyfile.exist?)
194
+ raise RubeePass::Error::FileNotFound.new(@keyfile)
195
+ elsif (!@keyfile.readable?)
196
+ raise RubeePass::Error::FileNotReadable.new(@keyfile)
197
+ end
198
+ end
180
199
  end
181
200
 
182
201
  def join_key_and_keyfile
@@ -264,28 +283,26 @@ class RubeePass
264
283
  loop do
265
284
  # Read block ID
266
285
  data = file.read(4)
267
- raise Error::InvalidGzipError.new if (data.nil?)
286
+ raise Error::InvalidGzip.new if (data.nil?)
268
287
  id = data.unpack("L*")[0]
269
- raise Error::InvalidGzipError.new if (block_id != id)
288
+ raise Error::InvalidGzip.new if (block_id != id)
270
289
 
271
290
  block_id += 1
272
291
 
273
292
  # Read expected hash
274
293
  data = file.read(32)
275
- raise Error::InvalidGzipError.new if (data.nil?)
294
+ raise Error::InvalidGzip.new if (data.nil?)
276
295
  expected_hash = data
277
296
 
278
297
  # Read size
279
298
  data = file.read(4)
280
- raise Error::InvalidGzipError.new if (data.nil?)
299
+ raise Error::InvalidGzip.new if (data.nil?)
281
300
  size = data.unpack("L*")[0]
282
301
 
283
302
  # Break is size is 0 and expected hash is all 0's
284
303
  if (size == 0)
285
304
  expected_hash.each_byte do |byte|
286
- if (byte != 0)
287
- raise Error::InvalidGzipError.new
288
- end
305
+ raise Error::InvalidGzip.new if (byte != 0)
289
306
  end
290
307
  break
291
308
  end
@@ -296,7 +313,7 @@ class RubeePass
296
313
 
297
314
  # Check that actual hash is same as expected hash
298
315
  if (actual_hash != expected_hash)
299
- raise Error::InvalidGzipError.new
316
+ raise Error::InvalidGzip.new
300
317
  end
301
318
 
302
319
  # Append data
@@ -310,11 +327,11 @@ class RubeePass
310
327
  def parse_xml
311
328
  doc = REXML::Document.new(@xml)
312
329
  if (doc.elements["KeePassFile/Root"].nil?)
313
- raise Error::InvalidXMLError.new
330
+ raise Error::InvalidXML.new
314
331
  end
315
332
 
316
333
  root = doc.elements["KeePassFile/Root"]
317
- @db = Group.from_xml(self, nil, root)
334
+ @db = Group.from_xml(self, nil, root, @colorize)
318
335
  end
319
336
  private :parse_xml
320
337
 
@@ -331,11 +348,11 @@ class RubeePass
331
348
  cipher.update(encrypted) + cipher.final
332
349
  )
333
350
  rescue OpenSSL::Cipher::CipherError => e
334
- raise Error::InvalidPasswordError.new
351
+ raise Error::InvalidPassword.new
335
352
  end
336
353
 
337
354
  if (data.read(32) != @header[@@STREAM_START_BYTES])
338
- raise Error::InvalidPasswordError.new
355
+ raise Error::InvalidPassword.new
339
356
  end
340
357
 
341
358
  @gzip = parse_gzip(data)
@@ -346,11 +363,11 @@ class RubeePass
346
363
  header = Hash.new
347
364
  loop do
348
365
  data = file.read(1)
349
- raise Error::InvalidHeaderError.new if (data.nil?)
366
+ raise Error::InvalidHeader.new if (data.nil?)
350
367
  id = data.unpack("C*")[0]
351
368
 
352
369
  data = file.read(2)
353
- raise Error::InvalidHeaderError.new if (data.nil?)
370
+ raise Error::InvalidHeader.new if (data.nil?)
354
371
  size = data.unpack("S*")[0]
355
372
 
356
373
  data = file.read(size)
@@ -371,11 +388,11 @@ class RubeePass
371
388
  (header[@@MASTER_SEED].length != 32) ||
372
389
  (header[@@TRANSFORM_SEED].length != 32)
373
390
  )
374
- raise Error::InvalidHeaderError.new
391
+ raise Error::InvalidHeader.new
375
392
  elsif (header[@@INNER_RANDOM_STREAM_ID] != irsi)
376
- raise Error::NotSalsaError.new
393
+ raise Error::NotSalsa.new
377
394
  elsif (header[@@CIPHER_ID].unpack("H*")[0] != aes)
378
- raise Error::NotAESError.new
395
+ raise Error::NotAES.new
379
396
  end
380
397
 
381
398
  @header = header
@@ -384,24 +401,20 @@ class RubeePass
384
401
 
385
402
  def read_magic_and_version(file)
386
403
  data = file.read(4)
387
- raise Error::InvalidMagicError.new if (data.nil?)
404
+ raise Error::InvalidMagic.new if (data.nil?)
388
405
  sig1 = data.unpack("L*")[0]
389
- if (sig1 != @@MAGIC_SIG1)
390
- raise Error::InvalidMagicError.new
391
- end
406
+ raise Error::InvalidMagic.new if (sig1 != @@MAGIC_SIG1)
392
407
 
393
408
  data = file.read(4)
394
- raise Error::InvalidMagicError.new if (data.nil?)
409
+ raise Error::InvalidMagic.new if (data.nil?)
395
410
  sig2 = data.unpack("L*")[0]
396
- if (sig2 != @@MAGIC_SIG2)
397
- raise Error::InvalidMagicError.new
398
- end
411
+ raise Error::InvalidMagic.new if (sig2 != @@MAGIC_SIG2)
399
412
 
400
413
  data = file.read(4)
401
- raise Error::InvalidVersionError.new if (data.nil?)
414
+ raise Error::InvalidVersion.new if (data.nil?)
402
415
  ver = data.unpack("L*")[0]
403
416
  if ((ver & 0xffff0000) != @@VERSION)
404
- raise Error::InvalidVersionError.new if (data.nil?)
417
+ raise Error::InvalidVersion.new if (data.nil?)
405
418
  end
406
419
  end
407
420
  private :read_magic_and_version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubeepass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Whittaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-18 00:00:00.000000000 Z
11
+ date: 2016-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '5.8'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 5.8.1
22
+ version: 5.8.4
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,27 +29,27 @@ dependencies:
29
29
  version: '5.8'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 5.8.1
32
+ version: 5.8.4
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rake
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '10.4'
39
+ version: '10.5'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 10.4.2
42
+ version: 10.5.0
43
43
  type: :development
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '10.4'
49
+ version: '10.5'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 10.4.2
52
+ version: 10.5.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: colorize
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ dependencies:
79
79
  version: '1.3'
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 1.3.1
82
+ version: 1.3.3
83
83
  type: :runtime
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,7 +89,27 @@ dependencies:
89
89
  version: '1.3'
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
- version: 1.3.1
92
+ version: 1.3.3
93
+ - !ruby/object:Gem::Dependency
94
+ name: json_config
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '0.1'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 0.1.1
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.1'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 0.1.1
93
113
  - !ruby/object:Gem::Dependency
94
114
  name: os
95
115
  requirement: !ruby/object:Gem::Requirement
@@ -139,7 +159,7 @@ dependencies:
139
159
  version: '0.1'
140
160
  - - ">="
141
161
  - !ruby/object:Gem::Version
142
- version: 0.1.1
162
+ version: 0.1.3
143
163
  type: :runtime
144
164
  prerelease: false
145
165
  version_requirements: !ruby/object:Gem::Requirement
@@ -149,7 +169,7 @@ dependencies:
149
169
  version: '0.1'
150
170
  - - ">="
151
171
  - !ruby/object:Gem::Version
152
- version: 0.1.1
172
+ version: 0.1.3
153
173
  description: Ruby KeePass 2.x implementation. Currently it is read-only.
154
174
  email: mjwhitta@gmail.com
155
175
  executables:
@@ -161,16 +181,18 @@ files:
161
181
  - lib/rubeepass.rb
162
182
  - lib/rubeepass/entry.rb
163
183
  - lib/rubeepass/error.rb
164
- - lib/rubeepass/error/invalid_gzip_error.rb
165
- - lib/rubeepass/error/invalid_header_error.rb
166
- - lib/rubeepass/error/invalid_magic_error.rb
167
- - lib/rubeepass/error/invalid_password_error.rb
168
- - lib/rubeepass/error/invalid_protected_data_error.rb
169
- - lib/rubeepass/error/invalid_protected_stream_key_error.rb
170
- - lib/rubeepass/error/invalid_version_error.rb
171
- - lib/rubeepass/error/invalid_xml_error.rb
172
- - lib/rubeepass/error/not_aes_error.rb
173
- - lib/rubeepass/error/not_salsa20_error.rb
184
+ - lib/rubeepass/error/file_not_found.rb
185
+ - lib/rubeepass/error/file_not_readable.rb
186
+ - lib/rubeepass/error/invalid_gzip.rb
187
+ - lib/rubeepass/error/invalid_header.rb
188
+ - lib/rubeepass/error/invalid_magic.rb
189
+ - lib/rubeepass/error/invalid_password.rb
190
+ - lib/rubeepass/error/invalid_protected_data.rb
191
+ - lib/rubeepass/error/invalid_protected_stream_key.rb
192
+ - lib/rubeepass/error/invalid_version.rb
193
+ - lib/rubeepass/error/invalid_xml.rb
194
+ - lib/rubeepass/error/not_aes.rb
195
+ - lib/rubeepass/error/not_salsa20.rb
174
196
  - lib/rubeepass/group.rb
175
197
  - lib/rubeepass/protected_decryptor.rb
176
198
  - lib/rubeepass/wish/cd_wish.rb