rubeepass 0.3.9 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 369d21017f882fa9c9f7255640b6d498a0990a00
4
- data.tar.gz: a48d53c24ce87d35611e13af2ced5e9bd1585ca4
3
+ metadata.gz: 198fd42f6442a724c48c2e9fed48dde20d381ce6
4
+ data.tar.gz: 632b3d39273d942925b56139da529b35a08ec2f4
5
5
  SHA512:
6
- metadata.gz: de43b254efde377d3efcc245715125edc28bfcf18b697823be773bf303a189142024f1f8428bab73828c8595fde3b31c53dc161a3d6136c1ba79689f08396e0f
7
- data.tar.gz: bc39deec9c478d2df9570b0158385669f6587fbf484e42788332dc8e26ca82a1a7cd6870c6fae294466bf15ed508c25f9dc21f2a92833a96836918cd84410122
6
+ metadata.gz: 1f1dc4135f2c8d9de6cc409ea99c44f0b2c4d78a2001c63ca2047639c7613bb9e458939604d1e3af6b2bab151b4a2fba329f799dde7c3a344ae1aa1f408791eb
7
+ data.tar.gz: 510391ec34652bfea7b32895d3d3b82c8727d9077c12cac06bd09875fe257e505fcb216870290ded1f3d083210cbc9f0a77e3045ed59c0bc374030016b11c08d
@@ -1,3 +1,4 @@
1
+ require "rexml/document"
1
2
  require "string"
2
3
 
3
4
  class RubeePass::Entry
@@ -43,15 +44,90 @@ class RubeePass::Entry
43
44
  return ret.join("\n")
44
45
  end
45
46
 
46
- def initialize(params)
47
- @group = params.fetch("Group", nil)
48
- @keepass = params.fetch("Keepass", nil)
49
- @notes = params.fetch("Notes", "")
50
- @password = params.fetch("Password", "")
51
- @title = params.fetch("Title", "")
52
- @url = params.fetch("URL", "")
53
- @username = params.fetch("UserName", "")
54
- @uuid = params.fetch("UUID", "")
47
+ def self.from_xml(keepass, parent, xml)
48
+ notes = ""
49
+ password = ""
50
+ title = ""
51
+ url = ""
52
+ username = ""
53
+
54
+ uuid = xml.elements["UUID"].text
55
+ uuid = "" if (uuid.nil?)
56
+
57
+ xml.elements.each("String") do |elem|
58
+ case elem.elements["Key"].text
59
+ when "Notes"
60
+ notes = elem.elements["Value"].text
61
+ notes = "" if (notes.nil?)
62
+ when "Password"
63
+ value = elem.elements["Value"]
64
+ if (value.attributes["Protected"] == "True")
65
+ password = handle_protected(keepass, value.text)
66
+ else
67
+ password = value.text
68
+ password = "" if (password.nil?)
69
+ end
70
+ when "Title"
71
+ title = elem.elements["Value"].text
72
+ title = "" if (title.nil?)
73
+ when "URL"
74
+ url = elem.elements["Value"].text
75
+ url = "" if (url.nil?)
76
+ when "UserName"
77
+ username = elem.elements["Value"].text
78
+ username = "" if (username.nil?)
79
+ end
80
+ end
81
+
82
+ # Handle protected data from history
83
+ xml.elements.each("History/Entry/String/Value") do |value|
84
+ if (value.attributes["Protected"] == "True")
85
+ handle_protected(keepass, value.text)
86
+ end
87
+ end
88
+
89
+ return RubeePass::Entry.new(
90
+ parent,
91
+ keepass,
92
+ notes,
93
+ password,
94
+ title,
95
+ url,
96
+ username,
97
+ uuid
98
+ )
99
+ end
100
+
101
+ def self.handle_protected(keepass, base64)
102
+ data = nil
103
+ begin
104
+ data = base64.unpack("m*")[0].fix
105
+ rescue ArgumentError => e
106
+ raise Error::InvalidProtectedDataError.new
107
+ end
108
+ raise Error::InvalidProtectedDataError.new if (data.nil?)
109
+
110
+ return keepass.protected_decryptor.add_to_stream(data)
111
+ end
112
+
113
+ def initialize(
114
+ group,
115
+ keepass,
116
+ notes,
117
+ password,
118
+ title,
119
+ url,
120
+ username,
121
+ uuid
122
+ )
123
+ @group = group
124
+ @keepass = keepass
125
+ @notes = notes
126
+ @password = password
127
+ @title = title
128
+ @url = url
129
+ @username = username
130
+ @uuid = uuid
55
131
 
56
132
  @path = @title
57
133
  @path = "#{@group.path}/#{@title}" if (@group)
@@ -95,7 +171,9 @@ class RubeePass::Entry
95
171
  def password
96
172
  return nil if (@keepass.nil?)
97
173
  begin
98
- return @keepass.protected_decryptor.get_password(@password)
174
+ return @keepass.protected_decryptor.get_password(
175
+ @password
176
+ )
99
177
  rescue
100
178
  return @password
101
179
  end
@@ -0,0 +1,7 @@
1
+ require "rubeepass/error"
2
+
3
+ class RubeePass::Error::InvalidXMLError < RubeePass::Error
4
+ def initialize
5
+ super("Invalid xml schema!")
6
+ end
7
+ end
@@ -8,5 +8,6 @@ require "rubeepass/error/invalid_password_error"
8
8
  require "rubeepass/error/invalid_protected_data_error"
9
9
  require "rubeepass/error/invalid_protected_stream_key_error"
10
10
  require "rubeepass/error/invalid_version_error"
11
+ require "rubeepass/error/invalid_xml_error"
11
12
  require "rubeepass/error/not_aes_error"
12
13
  require "rubeepass/error/not_salsa20_error"
@@ -1,3 +1,4 @@
1
+ require "rexml/document"
1
2
  require "string"
2
3
 
3
4
  class RubeePass::Group
@@ -23,8 +24,8 @@ class RubeePass::Group
23
24
  out = Array.new
24
25
  lvl = Array.new(level, " ").join
25
26
 
26
- group_details = [ "#{@name}".blue ]
27
- group_details[0] = "#{@path}".blue if (level == 0)
27
+ group_details = [ "#{@path}".blue ] if (level == 0)
28
+ group_details = [ "#{@name}".blue ] if (level != 0)
28
29
 
29
30
  group_details.each do |line|
30
31
  out.push("#{lvl}#{line}")
@@ -63,6 +64,52 @@ class RubeePass::Group
63
64
  return cwd
64
65
  end
65
66
 
67
+ def self.from_xml(keepass, parent, xml)
68
+ name = xml.elements["Name"].text if (parent)
69
+ name = "" if (name.nil?)
70
+ name = "/" if (parent.nil?)
71
+
72
+ notes = xml.elements["Notes"].text if (parent)
73
+ notes = "" if (notes.nil?)
74
+ notes = "" if (parent.nil?)
75
+
76
+ uuid = xml.elements["UUID"].text if (parent)
77
+ uuid = "" if (uuid.nil?)
78
+ uuid = "" if (parent.nil?)
79
+
80
+ group = RubeePass::Group.new(
81
+ parent,
82
+ keepass,
83
+ name,
84
+ notes,
85
+ uuid
86
+ )
87
+
88
+ if (xml.elements["Entry"])
89
+ xml.elements.each("Entry") do |entry_xml|
90
+ entry = RubeePass::Entry.from_xml(
91
+ keepass,
92
+ group,
93
+ entry_xml
94
+ )
95
+ group.entries[entry.title] = entry
96
+ end
97
+ end
98
+
99
+ if (xml.elements["Group"])
100
+ xml.elements.each("Group") do |group_xml|
101
+ child = RubeePass::Group.from_xml(
102
+ keepass,
103
+ group,
104
+ group_xml
105
+ )
106
+ group.groups[child.name] = child
107
+ end
108
+ end
109
+
110
+ return group
111
+ end
112
+
66
113
  def fuzzy_find(input)
67
114
  return [ [], [], [] ] if (@keepass.nil?)
68
115
 
@@ -114,13 +161,14 @@ class RubeePass::Group
114
161
  return false
115
162
  end
116
163
 
117
- def initialize(params)
164
+ def initialize(group, keepass, name, notes, uuid)
118
165
  @entries = Hash.new
119
- @group = params.fetch("Group", nil)
166
+ @group = group
120
167
  @groups = Hash.new
121
- @keepass = params.fetch("Keepass", nil)
122
- @name = params.fetch("Name", "")
123
- @uuid = params.fetch("UUID", "")
168
+ @keepass = keepass
169
+ @name = name
170
+ @notes = notes
171
+ @uuid = uuid
124
172
 
125
173
  @path = @name
126
174
  @path = "#{@group.path}/#{@name}" if (@group)
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 "rexml/document"
5
6
  require "scoobydoo"
6
7
  require "shellwords"
7
8
  require "uri"
@@ -169,19 +170,6 @@ class RubeePass
169
170
  return @db.fuzzy_find(input)
170
171
  end
171
172
 
172
- def handle_protected(base64)
173
- data = nil
174
- begin
175
- data = base64.unpack("m*")[0].fix
176
- rescue ArgumentError => e
177
- raise Error::InvalidProtectedDataError.new
178
- end
179
- raise Error::InvalidProtectedDataError.new if (data.nil?)
180
-
181
- return @protected_decryptor.add_to_stream(data)
182
- end
183
- private :handle_protected
184
-
185
173
  def initialize(kdbx, password, keyfile = nil)
186
174
  @kdbx = kdbx
187
175
  @keyfile = keyfile
@@ -316,104 +304,14 @@ class RubeePass
316
304
  end
317
305
  private :parse_gzip
318
306
 
319
- # Horrible attempt at parsing xml. Someday I might use a library.
320
307
  def parse_xml
321
- curr = Group.new({"Keepass" => self, "Name" => "/"})
322
- entry_params = Hash.new
323
- group_params = Hash.new
324
- ignore = true
325
- inside_value = false
326
- status = nil
327
-
328
- @xml.gsub("<", "\n<").each_line do |line|
329
- line.strip!
330
-
331
- case line
332
- when "<History>"
333
- ignore = true
334
- next
335
- when "</History>"
336
- ignore = false
337
- next
338
- when "<Root>"
339
- ignore = false
340
- next
341
- when "</Root>"
342
- break
343
- when "</Value>"
344
- status = nil
345
- inside_value = false
346
- next
347
- when ""
348
- next if (!inside_value)
349
- end
350
-
351
- line = CGI::unescapeHTML(line)
352
- line = URI::unescape(line)
353
- if (!line.valid_encoding?)
354
- line = line.encode(
355
- "UTF-16be",
356
- :invalid=>:replace,
357
- :replace=>"?"
358
- ).encode('UTF-8')
359
- end
360
-
361
- # Handle values with newlines
362
- if (inside_value && !ignore)
363
- entry_params[status] += "\n#{line}"
364
- next
365
- end
366
-
367
- # Always handle protected data
368
- case line
369
- when %r{^<Value Protected="True">.+}
370
- line.gsub!(%r{^<Value Protected="True">}, "")
371
- if (ignore)
372
- handle_protected(line)
373
- else
374
- entry_params[status] = handle_protected(line)
375
- end
376
- next
377
- else
378
- next if (ignore)
379
- end
380
-
381
- case line
382
- when "<Entry>"
383
- entry_params = { "Keepass" => self, "Group" => curr }
384
- when "</Entry>"
385
- entry = Entry.new(entry_params)
386
- curr.entries[entry.title] = entry
387
- when "<Group>"
388
- group_params = { "Keepass" => self, "Group" => curr }
389
- when "</Group>"
390
- curr = curr.group
391
- break if (curr.nil?)
392
- when %r{^<Key>.+}
393
- status = line.gsub(%r{^<Key>}, "")
394
- when %r{^<Name>.+}
395
- line.gsub!(%r{^<Name>}, "")
396
- group_params["Name"] = line
397
-
398
- group = Group.new(group_params)
399
- curr.groups[group.name] = group
400
- curr = group
401
- when %r{^<UUID>.+}
402
- uuid = line.gsub(%r{^<UUID>}, "")
403
- if (group_params["UUID"].nil?)
404
- group_params["UUID"] = uuid
405
- else
406
- entry_params["UUID"] = uuid
407
- end
408
- when %r{^<Value>.*}
409
- line.gsub!(%r{^<Value>}, "")
410
- line = "" if (line.nil?)
411
- entry_params[status] = line
412
- inside_value = true
413
- end
308
+ doc = REXML::Document.new(@xml)
309
+ if (doc.elements["KeePassFile/Root"].nil?)
310
+ raise Error::InvalidXMLError.new
414
311
  end
415
312
 
416
- @db = curr
313
+ root = doc.elements["KeePassFile/Root"]
314
+ @db = Group.from_xml(self, nil, root)
417
315
  end
418
316
  private :parse_xml
419
317
 
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.3.9
4
+ version: 0.4.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-01-08 00:00:00.000000000 Z
11
+ date: 2016-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -148,6 +148,7 @@ files:
148
148
  - lib/rubeepass/error/invalid_protected_data_error.rb
149
149
  - lib/rubeepass/error/invalid_protected_stream_key_error.rb
150
150
  - lib/rubeepass/error/invalid_version_error.rb
151
+ - lib/rubeepass/error/invalid_xml_error.rb
151
152
  - lib/rubeepass/error/not_aes_error.rb
152
153
  - lib/rubeepass/error/not_salsa20_error.rb
153
154
  - lib/rubeepass/group.rb