rubeepass 0.3.9 → 0.4.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: 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