reedb 0.10.rc1
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 +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +38 -0
- data/Rakefile +2 -0
- data/bin/reedbd +62 -0
- data/lib/reedb.rb +739 -0
- data/lib/reedb/config.rb +24 -0
- data/lib/reedb/constants.rb +42 -0
- data/lib/reedb/daemon_wrapper.rb +617 -0
- data/lib/reedb/datafile.rb +268 -0
- data/lib/reedb/errors/daemon_errors.rb +34 -0
- data/lib/reedb/errors/encryption_errors.rb +29 -0
- data/lib/reedb/errors/vault_errors.rb +39 -0
- data/lib/reedb/reevault.rb +547 -0
- data/lib/reedb/security/aes.rb +94 -0
- data/lib/reedb/security/encryption.rb +64 -0
- data/lib/reedb/security/multifish.rb +15 -0
- data/lib/reedb/security/secure_hash.rb +131 -0
- data/lib/reedb/security/twofish.rb +14 -0
- data/lib/reedb/utils/logger.rb +97 -0
- data/lib/reedb/utils/meta_vault.rb +28 -0
- data/lib/reedb/utils/sorting.rb +49 -0
- data/lib/reedb/utils/utilities.rb +121 -0
- data/lib/reedb/utils/uuids.rb +375 -0
- data/lib/reedb/utils/version.rb +101 -0
- data/reedb.gemspec +31 -0
- data/tests/daemons/reedb.rb +27 -0
- data/tests/layout.rb +24 -0
- data/tests/networking/client.rb +14 -0
- data/tests/networking/server.rb +14 -0
- data/tests/play.rb +5 -0
- data/tests/serialisation.rb +49 -0
- data/tests/tests.rb +64 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 11820940b0e80cda5ea4e0ab59fb2dd4b5a06189
|
4
|
+
data.tar.gz: f6ed0c7e514bfebb4b25750e7583dbb2fdc2c0c9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1c960ebf6cf718de201067246c8eb13fecd43c40f23482d2e6d594ae5229ed42ec2fc2f3642ef4c26f89d8d26401d570d31bbc1388fc8138395f0b4c044a7d7f
|
7
|
+
data.tar.gz: 2f0ecd887ad56e8bc3a04c84b2a8e5bf97ba37d4cb69980a573e19d5c33c595867a58c3146a1d61b81fd61f624a208cb851956ad08d3072bbb3cb6cee8628f31
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
reedb
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.5
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in reedb.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
# Security!
|
7
|
+
gem 'aes', '>=0.5.0'
|
8
|
+
gem 'twofish', '>=1.0.5'
|
9
|
+
gem 'digest-tiger', '~> 1.0.2'
|
10
|
+
|
11
|
+
# Other stuff that's important
|
12
|
+
gem 'json', '~> 1.8.2'
|
13
|
+
gem 'daemons', '~> 1.2.2'
|
14
|
+
gem 'sinatra', '~> 1.4.6'
|
15
|
+
gem 'hashids', '~> 1.0.2'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
reedb (0.9.9.pre.RC1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
aes (0.5.0)
|
10
|
+
daemons (1.2.2)
|
11
|
+
digest-tiger (1.0.2)
|
12
|
+
hashids (1.0.2)
|
13
|
+
json (1.8.2)
|
14
|
+
rack (1.6.1)
|
15
|
+
rack-protection (1.5.3)
|
16
|
+
rack
|
17
|
+
rake (10.4.2)
|
18
|
+
sinatra (1.4.6)
|
19
|
+
rack (~> 1.4)
|
20
|
+
rack-protection (~> 1.4)
|
21
|
+
tilt (>= 1.3, < 3)
|
22
|
+
tilt (2.0.1)
|
23
|
+
twofish (1.0.5)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
aes (>= 0.5.0)
|
30
|
+
bundler (~> 1.7)
|
31
|
+
daemons (~> 1.2.2)
|
32
|
+
digest-tiger (~> 1.0.2)
|
33
|
+
hashids (~> 1.0.2)
|
34
|
+
json (~> 1.8.2)
|
35
|
+
rake (~> 10.0)
|
36
|
+
reedb!
|
37
|
+
sinatra (~> 1.4.6)
|
38
|
+
twofish (>= 1.0.5)
|
data/Rakefile
ADDED
data/bin/reedbd
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# ====================================================
|
4
|
+
# Copyright 2015 Lonely Robot (see @author)
|
5
|
+
# @author: Katharina Sabel | www.2rsoftworks.de
|
6
|
+
#
|
7
|
+
# Distributed under the GNU Lesser GPL Version 3
|
8
|
+
# (See accompanying LICENSE file or get a copy at
|
9
|
+
# https://www.gnu.org/licenses/lgpl.html)
|
10
|
+
# ====================================================
|
11
|
+
|
12
|
+
|
13
|
+
# Very simple wrapper script to start the Reedb daemon.
|
14
|
+
require 'reedb/constants'
|
15
|
+
|
16
|
+
NAME = 'reedbd'
|
17
|
+
|
18
|
+
if File.basename(__FILE__) == NAME
|
19
|
+
if ARGV.include? '--version'
|
20
|
+
puts Reedb::VERSION
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
if ARGV == []
|
25
|
+
puts "[ERROR]: Invalid application arguments!"
|
26
|
+
puts "Usage: reedb [daemon options] -- [reedb options]
|
27
|
+
|
28
|
+
Available [reedb options]:
|
29
|
+
-l, --pw-length INTEGER Define minimal passphrase length (Default: 12)
|
30
|
+
-p, --port INTEGER Change the listener port. May break your setup!
|
31
|
+
-a, --app-path STRING Change the path for the reedb config files/ logs. (default in ~)
|
32
|
+
-v, --verbose Enable verbose logging about the Reedb daemon.
|
33
|
+
-d, --no-daemon Don't run Reedb as a background daemon. Log to STOUT instead of log file.
|
34
|
+
|
35
|
+
Available [daemon options]:
|
36
|
+
start Start an instance of the #{NAME} daemon
|
37
|
+
stop Stop all instances of the #{NAME} daemon
|
38
|
+
restart Stop all and restart a new instance of #{NAME} afterwards
|
39
|
+
status Show status (PID) of #{NAME} daemon instance
|
40
|
+
|
41
|
+
Common options:
|
42
|
+
--version Show #{NAME} version"
|
43
|
+
|
44
|
+
# Then exits the application
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
options = {
|
49
|
+
:app_name => "reedb",
|
50
|
+
:backtrace => true,
|
51
|
+
# :monitor => true,
|
52
|
+
# :ontop => true
|
53
|
+
}
|
54
|
+
|
55
|
+
spec = Gem::Specification.find_by_name("reedb")
|
56
|
+
(puts "Error: reedb not installed!" ; exit) unless spec
|
57
|
+
path = (spec.gem_dir) + "/lib/reedb"
|
58
|
+
|
59
|
+
require 'daemons'
|
60
|
+
require 'reedb'
|
61
|
+
Daemons.run(File.join(path, 'daemon_wrapper.rb'), options)
|
62
|
+
end
|
data/lib/reedb.rb
ADDED
@@ -0,0 +1,739 @@
|
|
1
|
+
# ====================================================
|
2
|
+
# Copyright 2015 Lonely Robot (see @author)
|
3
|
+
# @author: Katharina Sabel | www.2rsoftworks.de
|
4
|
+
#
|
5
|
+
# Distributed under the GNU Lesser GPL Version 3
|
6
|
+
# (See accompanying LICENSE file or get a copy at
|
7
|
+
# https://www.gnu.org/licenses/lgpl.html)
|
8
|
+
# ====================================================
|
9
|
+
|
10
|
+
# Internal requirements
|
11
|
+
require_relative 'reedb/errors/daemon_errors'
|
12
|
+
|
13
|
+
require_relative 'reedb/utils/meta_vault'
|
14
|
+
require_relative 'reedb/utils/utilities'
|
15
|
+
require_relative 'reedb/utils/logger'
|
16
|
+
require_relative 'reedb/utils/uuids'
|
17
|
+
|
18
|
+
require_relative 'reedb/constants'
|
19
|
+
require_relative 'reedb/reevault'
|
20
|
+
|
21
|
+
|
22
|
+
# System requirements
|
23
|
+
require 'securerandom'
|
24
|
+
|
25
|
+
module Reedb
|
26
|
+
class << self
|
27
|
+
# Returns the platform/ architecture of the daemon and vault handler
|
28
|
+
|
29
|
+
def archos() (return @@archos) end
|
30
|
+
|
31
|
+
# Returns whether or not this is a daemon
|
32
|
+
def daemon?() (return @@daemon) end
|
33
|
+
|
34
|
+
# Returns the minimum passphrase length is
|
35
|
+
def passlength() (return @@pw_length) end
|
36
|
+
|
37
|
+
# Returns whether verbose mode is enabled
|
38
|
+
def verbose?() (return @@verbose) end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def self.included(api)
|
43
|
+
class << api
|
44
|
+
|
45
|
+
@@counter = 0
|
46
|
+
@@started = false
|
47
|
+
|
48
|
+
# Some more runtime variables
|
49
|
+
@@path = Reedb::DEF_MASTER_PATH
|
50
|
+
@@config_path = Reedb::DEF_MASTER_PATH
|
51
|
+
@@no_token = false
|
52
|
+
@@verbose = false
|
53
|
+
@@pw_length = -1
|
54
|
+
@@cleanup = true
|
55
|
+
@@daemon = true
|
56
|
+
@@archos = nil
|
57
|
+
|
58
|
+
# Stores the active vaults
|
59
|
+
@@active_vaults = {}
|
60
|
+
|
61
|
+
# Stores the active tokens
|
62
|
+
@@tokens = {}
|
63
|
+
|
64
|
+
# Stores the master configuration
|
65
|
+
@@config = nil
|
66
|
+
|
67
|
+
# PRIVATE FUNCTIONS BELOW
|
68
|
+
private
|
69
|
+
|
70
|
+
# Generates an authentication token for vault access.
|
71
|
+
# The function also adds the token, bound to the vault name, to the
|
72
|
+
# @@tokens set.
|
73
|
+
#
|
74
|
+
# Params: 'name' of the vault
|
75
|
+
# 'path' of the vault
|
76
|
+
#
|
77
|
+
# => Base64 encoded token
|
78
|
+
#
|
79
|
+
def generate_token(uuid, path)
|
80
|
+
# Concatinates the token together and base64 encodes it
|
81
|
+
token = Base64.encode64("#{SecureRandom.base64(Reedb::TOKEN_BYTE_SIZE)}--#{uuid}--#{SecureRandom.base64(Reedb::TOKEN_BYTE_SIZE)}--#{path}--#{SecureRandom.base64(Reedb::TOKEN_BYTE_SIZE)}")
|
82
|
+
token.delete!("\n")
|
83
|
+
@@tokens[token] = [] unless @@tokens.include?(token)
|
84
|
+
@@tokens[token] << uuid
|
85
|
+
update_tracked_vault("#{uuid}", nil, nil, nil, token)
|
86
|
+
return token
|
87
|
+
end
|
88
|
+
|
89
|
+
# Writes a vault into a tracking file for the user
|
90
|
+
# That means that the vault will be tracked next time
|
91
|
+
# Reedb starts
|
92
|
+
#
|
93
|
+
# Params: name => Public vault name
|
94
|
+
# path => Location on the system
|
95
|
+
# tokens => Authentication token for applications
|
96
|
+
#
|
97
|
+
def track_vault(name, path, size, uuid)
|
98
|
+
@@config[:vaults]["#{uuid}"] = {} unless @@config[:vaults].include?(uuid)
|
99
|
+
|
100
|
+
# Adds actual size as soon as the vault gets unlocked by an application
|
101
|
+
@@config[:vaults]["#{uuid}"][:meta] = MetaVault.new("#{name}", "#{path}", size, "#{uuid}")
|
102
|
+
@@config[:vaults]["#{uuid}"][:tokens] = [] unless @@config[:vaults]["#{uuid}"][:tokens]
|
103
|
+
@@config[:vaults]["#{uuid}"][:tokens] = []
|
104
|
+
|
105
|
+
write_config
|
106
|
+
end
|
107
|
+
|
108
|
+
def untrack_vault uuid
|
109
|
+
@@config[:vaults]["#{uuid}"] = nil if @@config[:vaults].include?(uuid)
|
110
|
+
end
|
111
|
+
|
112
|
+
def update_tracked_vault(uuid, name, path, size, token)
|
113
|
+
token.delete!("\n")
|
114
|
+
return nil unless @@config[:vaults].include?(uuid)
|
115
|
+
|
116
|
+
@@config[:vaults]["#{uuid}"][:meta].name = name if name
|
117
|
+
@@config[:vaults]["#{uuid}"][:meta].path = path if path
|
118
|
+
@@config[:vaults]["#{uuid}"][:meta].size = size if size
|
119
|
+
|
120
|
+
@@config[:vaults]["#{uuid}"][:tokens] = [] unless @@config[:vaults]["#{uuid}"][:tokens]
|
121
|
+
@@config[:vaults]["#{uuid}"][:tokens] << token if token
|
122
|
+
|
123
|
+
write_config
|
124
|
+
end
|
125
|
+
|
126
|
+
# Removes a token from a vault config thus removing any access that token had.
|
127
|
+
#
|
128
|
+
def remove_token(uuid, token)
|
129
|
+
token.delete!("\n")
|
130
|
+
return nil unless @@config[:vaults].include?(uuid)
|
131
|
+
return nil unless @@config[:vaults]["#{uuid}"][:tokens].include?(token)
|
132
|
+
|
133
|
+
@@config[:vaults]["#{uuid}"][:tokens].delete(token)
|
134
|
+
write_config
|
135
|
+
end
|
136
|
+
|
137
|
+
# Caches the config file to @@config
|
138
|
+
#
|
139
|
+
#
|
140
|
+
def cache_config
|
141
|
+
# Now read vault information and put it into @@active_vaults field
|
142
|
+
if File.exist?("#{@@config_path}")
|
143
|
+
read_config
|
144
|
+
else
|
145
|
+
# Creates some dummy info
|
146
|
+
@@config = {}
|
147
|
+
@@config[:global] = {}
|
148
|
+
@@config[:global][:logs] = :default
|
149
|
+
@@config[:vaults] = {}
|
150
|
+
|
151
|
+
# Writes the config to file with Base64 encoding
|
152
|
+
write_config
|
153
|
+
FileUtils::chmod_R(0744, "#{@@config_path}")
|
154
|
+
end
|
155
|
+
|
156
|
+
check_vault_integreties if @@cleanup
|
157
|
+
|
158
|
+
# At this point @@config has been loaded
|
159
|
+
vault_count = @@config[:vaults].size
|
160
|
+
DaemonLogger.write("Found #{vault_count} vault(s) on the system.", "debug")
|
161
|
+
end
|
162
|
+
|
163
|
+
# Check vault integreties here!
|
164
|
+
# Will try every vault in the config and remove the ones that are no longer
|
165
|
+
# available to avoid errors and access corruptions
|
166
|
+
#
|
167
|
+
def check_vault_integreties
|
168
|
+
# Vaults that will be marked for removal
|
169
|
+
marked = []
|
170
|
+
@@config[:vaults].each do |uuid, data|
|
171
|
+
unless ReeVault.new(data[:meta].name, data[:meta].path, :auto).try?
|
172
|
+
marked << uuid
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
marked.each do |uuid|
|
177
|
+
# puts "Removing: #{uuid}"
|
178
|
+
DaemonLogger.write("Removing corrupted vault #{uuid}", 'warn')
|
179
|
+
@@config[:vaults].delete(uuid)
|
180
|
+
end
|
181
|
+
write_config
|
182
|
+
end
|
183
|
+
|
184
|
+
def write_config
|
185
|
+
data = Marshal.dump(@@config)
|
186
|
+
File.open(@@config_path, 'wb+') { |file| file.write(data) }
|
187
|
+
read_config
|
188
|
+
end
|
189
|
+
|
190
|
+
def read_config
|
191
|
+
data = File.open(@@config_path, "rb").read()
|
192
|
+
@@config = Marshal.load(data)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Core submodule of the Interface stack
|
198
|
+
module Core
|
199
|
+
include Reedb
|
200
|
+
|
201
|
+
class << self
|
202
|
+
|
203
|
+
def init(options)
|
204
|
+
@@daemon = if options.include?(:daemon) then options[:daemon] else true end
|
205
|
+
@@archos = options[:os]
|
206
|
+
@@pw_length = options[:pw_length]
|
207
|
+
@@verbose = if options.include?(:verbose) then options[:verbose] else false end
|
208
|
+
@@no_token = if options.include?(:no_token) then options[:no_token] else false end
|
209
|
+
|
210
|
+
if @@no_token
|
211
|
+
puts "NO_TOKEN mode has not been implemented yet! Please just use token authentication mode."
|
212
|
+
@@no_token = false
|
213
|
+
end
|
214
|
+
|
215
|
+
@@path = if options.include?(:path) then options[:path] else "&&HOME&&" end
|
216
|
+
|
217
|
+
# Enable cleanup mode
|
218
|
+
# This means that the config will be cleaned and unused tokens removed
|
219
|
+
# instead of leaving them in the file and configurations.
|
220
|
+
# It is recommended to use cleanup mode.
|
221
|
+
#
|
222
|
+
@@cleanup = if options.include?(:cleanup) then options[:cleanup] else true end
|
223
|
+
|
224
|
+
# Set of vaults that map a VaultBuffer to the vault itself.
|
225
|
+
# Never exposed outside the API
|
226
|
+
#
|
227
|
+
@@active_vaults = {}
|
228
|
+
|
229
|
+
# List of tokens authorised for this daemon. Maps tokens to vault names.
|
230
|
+
# This is used for authentication and never exposed to the outside API
|
231
|
+
# NOTE! This is not used when the :no_token option is enabled
|
232
|
+
#
|
233
|
+
@@tokens = {} unless @@no_token
|
234
|
+
|
235
|
+
if @@archos == :linux
|
236
|
+
master_path = File.expand_path('~/.config/reedb/')
|
237
|
+
|
238
|
+
# Puts the folder in /etc if running as root
|
239
|
+
master_path = "/etc/reedb" if Utilities::parse_user == 'root'
|
240
|
+
|
241
|
+
log_path = File.expand_path('~/.config/reedb/logs/')
|
242
|
+
@@config_path = File.join("#{master_path}", "master.cfg")
|
243
|
+
|
244
|
+
elsif @@archos == :osx
|
245
|
+
master_path = File.expand_path('~/Library/Application\ Support/reedb/')
|
246
|
+
log_path = File.expand_path('~/Library/Application\ Support/reedb/logs/')
|
247
|
+
@@config_path = File.join("#{master_path}", "master.cfg")
|
248
|
+
else
|
249
|
+
# Windows crap
|
250
|
+
end
|
251
|
+
|
252
|
+
# Changing file permissions. Does this do ANYTHING on windows?
|
253
|
+
FileUtils::mkdir_p("#{log_path}") # 744 (owned by $USER)
|
254
|
+
FileUtils::chmod_R(0744, "#{log_path}")
|
255
|
+
FileUtils::chmod_R(0744, "#{master_path}")
|
256
|
+
|
257
|
+
Reedb::DaemonLogger.setup("#{log_path}")
|
258
|
+
@@started = true
|
259
|
+
Reedb::DaemonLogger.write("Reedb was started successfully. Reading vault information now...", 'debug')
|
260
|
+
|
261
|
+
# Now cache the config
|
262
|
+
cache_config
|
263
|
+
|
264
|
+
# Open debounce tread and mirror current vault information onto it.
|
265
|
+
# debounce_handler
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
def terminate(reason = nil)
|
270
|
+
puts "Must start process first" unless @@started
|
271
|
+
|
272
|
+
new_reason = "unknown reason"
|
273
|
+
new_reason = "a user request" if reason == "user"
|
274
|
+
new_reason = "a system request" if reason == "root"
|
275
|
+
|
276
|
+
# My first easter-egg. Yay! :)
|
277
|
+
new_reason = "the illuminati" if reason == "aliens"
|
278
|
+
|
279
|
+
DaemonLogger.write("[TERMINATION]: Scheduling termination because of #{new_reason}.")
|
280
|
+
|
281
|
+
# TODO: Close the debounce thread here.
|
282
|
+
|
283
|
+
@@started = false
|
284
|
+
# Closing open vaults here
|
285
|
+
counter = 0 ; @@active_vaults.each { |k, v| v.close; counter += 1 }
|
286
|
+
DaemonLogger.write("[TERMINATION]: Closed #{counter} vaults. Done!")
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Config submodule of the Interface stack
|
292
|
+
module Config
|
293
|
+
module Master
|
294
|
+
include Reedb
|
295
|
+
class << self
|
296
|
+
|
297
|
+
def dump_config
|
298
|
+
return @@config
|
299
|
+
end
|
300
|
+
|
301
|
+
# Set a global timeout time to all vaults. Determine when a vault will
|
302
|
+
# be unloaded or the daemon will lock itself.
|
303
|
+
# Time provided in seconds
|
304
|
+
#
|
305
|
+
def global_timeout dt
|
306
|
+
end
|
307
|
+
|
308
|
+
# Set the log state of the daemon. That determines what error calls will
|
309
|
+
# be logged and what will be ommited.
|
310
|
+
#
|
311
|
+
def logging_state state
|
312
|
+
end
|
313
|
+
|
314
|
+
# Define a minimal passphrase length for vaults to have. This can
|
315
|
+
# break access to vaults if they were created on a different system
|
316
|
+
# so be careful with this!
|
317
|
+
#
|
318
|
+
def passphrase_length length
|
319
|
+
end
|
320
|
+
|
321
|
+
# Cleans the config file of broken vaults and config items. This is
|
322
|
+
# being done by default when operating in cleanup mode.
|
323
|
+
#
|
324
|
+
def clean_config
|
325
|
+
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
module Vault
|
331
|
+
include Reedb
|
332
|
+
class << self
|
333
|
+
def set_vault_timeout dt
|
334
|
+
end
|
335
|
+
|
336
|
+
def add_header_field(field, type)
|
337
|
+
end
|
338
|
+
|
339
|
+
def change_passphrase(old_phrase, new_phrase)
|
340
|
+
end
|
341
|
+
|
342
|
+
def read_config
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
# Vault submodule of the Interface stack
|
349
|
+
module Vault
|
350
|
+
include Reedb
|
351
|
+
|
352
|
+
class << self
|
353
|
+
|
354
|
+
# Returns a list of all vaults tracked by Reedb (by the current user).
|
355
|
+
# Vaults are ordered in a dictionary under their UUID that's used by the
|
356
|
+
# Reedb daemon.
|
357
|
+
#
|
358
|
+
# => A compiled JSON of vaults with uuid, name, path and size
|
359
|
+
#
|
360
|
+
def available_vaults
|
361
|
+
available = {}
|
362
|
+
|
363
|
+
@@config[:vaults].each do |uuid, value|
|
364
|
+
# puts @@config[:vaults]["#{uuid}"]
|
365
|
+
available["#{uuid}"] = {}
|
366
|
+
available["#{uuid}"][:name] = value[:meta].name
|
367
|
+
available["#{uuid}"][:path] = value[:meta].path
|
368
|
+
available["#{uuid}"][:size] = value[:meta].size
|
369
|
+
end
|
370
|
+
return available
|
371
|
+
end
|
372
|
+
|
373
|
+
# Creates a new vault on the current system. Returns nil if vault already existed at
|
374
|
+
# location. Returns a token if the creation and authentication was successful on the
|
375
|
+
# user side.
|
376
|
+
# Also adds that token to the @@tokens list
|
377
|
+
#
|
378
|
+
# THROWS A LOT OF EXCEPTIONS!
|
379
|
+
#
|
380
|
+
#
|
381
|
+
# Params:
|
382
|
+
# 'name' of the vault
|
383
|
+
# 'path' of the vault
|
384
|
+
# user 'passphrase'
|
385
|
+
# 'encryption' method (:aes, :twofish, :auto)
|
386
|
+
#
|
387
|
+
# => Base64 encoded token | nil if errors occured.
|
388
|
+
#
|
389
|
+
def create_vault(name, path, passphrase, encryption = :auto)
|
390
|
+
# Creates new UUIDs until one is found that doesn't already exist in the scope
|
391
|
+
uuid = nil
|
392
|
+
loop do
|
393
|
+
uuid = UUID::create_v1
|
394
|
+
(break) unless @@config[:vaults].include?(uuid)
|
395
|
+
end
|
396
|
+
|
397
|
+
# Create actual Vault object
|
398
|
+
# This throws errors!
|
399
|
+
tmp_vault = ReeVault.new("#{name}", "#{path}", encryption).create("#{passphrase}")
|
400
|
+
|
401
|
+
# Creates a metavault with name, path, size and uuid to be tracked on the system
|
402
|
+
# metavault = MetaVault.new("#{name}", "#{path}", 0, "#{uuid}")
|
403
|
+
|
404
|
+
# Adds vault to the active set of vaults
|
405
|
+
@@active_vaults[uuid] = tmp_vault
|
406
|
+
|
407
|
+
# Generates a token
|
408
|
+
unless @@no_token
|
409
|
+
token = generate_token(uuid, path)
|
410
|
+
track_vault(name, path, 0, uuid)
|
411
|
+
return token.delete!("\n")
|
412
|
+
end
|
413
|
+
|
414
|
+
# In case token authentication was disabled
|
415
|
+
track_vault(uuid, nil)
|
416
|
+
return nil
|
417
|
+
end
|
418
|
+
|
419
|
+
|
420
|
+
# ONLY PERMITTED WHEN IN NO_TOKEN MODE! WILL BE DISABLED AUTOMATICALLY WHEN
|
421
|
+
# USING THE HTTP MODULE!
|
422
|
+
#
|
423
|
+
# Loads a vault with a UUID and passphrase into the current vault set.
|
424
|
+
# Ignores the token set (as not applicable when in token mode) and simply
|
425
|
+
# returns a confirmation that vault access was granted.
|
426
|
+
#
|
427
|
+
def access_vault(uuid, passphrase)
|
428
|
+
raise FunctionNotImplementedError.new, "This has not been implemented yet! Use token authentication via the DAEMON module."
|
429
|
+
return false
|
430
|
+
end
|
431
|
+
|
432
|
+
|
433
|
+
# Removes a vault from the file system. This requires special privileges
|
434
|
+
# to do via this interface to prevent deleting vaults without the users
|
435
|
+
# permission. Will also fire a user interrupt to alert them of this
|
436
|
+
# behaviour depending on platform.
|
437
|
+
#
|
438
|
+
# Params:
|
439
|
+
# 'uuid' of the vault
|
440
|
+
# 'passphrase' of the vault
|
441
|
+
# 'token' of an application that needs to be authorised
|
442
|
+
#
|
443
|
+
# => Returns boolean describing success
|
444
|
+
#
|
445
|
+
def remove_vault(uuid, passphrase, token)
|
446
|
+
token.delete!("\n")
|
447
|
+
# Returns false if that token isn't authorised
|
448
|
+
return false unless @@tokens[token].include?(uuid)
|
449
|
+
|
450
|
+
# Return false if vault has never been scoped before
|
451
|
+
return false unless @@config[:vaults].include?(uuid)
|
452
|
+
|
453
|
+
# Return false if vault is currently locked
|
454
|
+
return false if @@active_vaults[uuid].locked?
|
455
|
+
|
456
|
+
# Mark a vault for removal and only actually
|
457
|
+
raise FunctionNotImplementedError.new, "This has not been implemented yet! Don't do this."
|
458
|
+
return false
|
459
|
+
end
|
460
|
+
|
461
|
+
# Adds a new vault to the tracking scope of this Reedb daemon. Does not grant access
|
462
|
+
# or generate a new token for application interaction.
|
463
|
+
# On a new install usually called just before requesting a token
|
464
|
+
#
|
465
|
+
# Params: 'name' of the vault
|
466
|
+
# 'path' on the systen
|
467
|
+
#
|
468
|
+
def scope_vault(name, path)
|
469
|
+
# Checks if that specific vault was already scoped
|
470
|
+
@@config[:vaults].each do |key, value|
|
471
|
+
if value[:meta].name == "#{name}" && value[:meta].path == "#{path}"
|
472
|
+
DaemonLogger.write("Vault already scoped at #{path}", 'info')
|
473
|
+
raise VaultAlreadyScopedError.new, "Vault #{name} already scoped!"
|
474
|
+
return false
|
475
|
+
end
|
476
|
+
end
|
477
|
+
vault = ReeVault.new("#{name}", "#{path}", :auto)
|
478
|
+
# If it hasn't, proceed here
|
479
|
+
if vault.try?
|
480
|
+
uuid = nil
|
481
|
+
loop do
|
482
|
+
uuid = UUID::create_v1
|
483
|
+
(break) unless @@config[:vaults].include?(uuid)
|
484
|
+
end
|
485
|
+
|
486
|
+
# At this point a vault has been confirmed and a UUID generated
|
487
|
+
track_vault(name, path, vault.count, "#{uuid}")
|
488
|
+
DaemonLogger.write("Vault successfully scoped at #{path}", 'info')
|
489
|
+
cache_config
|
490
|
+
return true
|
491
|
+
else
|
492
|
+
DaemonLogger.write("Tried to scope empty target at #{path}", 'warn')
|
493
|
+
raise VaultDoesNotExistError.new, "Tried to scope empty target at #{path}"
|
494
|
+
return false
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
# Removes a vault from the application scope with a uuid.
|
499
|
+
# Closes the vault from the active vault set.
|
500
|
+
#
|
501
|
+
# Returns nil if no such vault was scoped before.
|
502
|
+
#
|
503
|
+
def unscope_vault(uuid)
|
504
|
+
unless @@config[:vaults]["#{uuid}"]
|
505
|
+
raise VaultNotScopedError.new, "Vault #{name} not scoped!"
|
506
|
+
return nilp
|
507
|
+
end
|
508
|
+
|
509
|
+
path = @@config[:vaults]["#{uuid}"][:path]
|
510
|
+
DaemonLogger.write("Unscoping vault #{uuid} at #{path}")
|
511
|
+
@@active_vaults["#{uuid}"].close if @@active_vaults["#{uuid}"]
|
512
|
+
@@config[:vaults].delete("#{uuid}")
|
513
|
+
cache_config
|
514
|
+
end
|
515
|
+
|
516
|
+
# Request token for a vault permanently.
|
517
|
+
# Only used if @@no_token == false. Unlocks a vault as well
|
518
|
+
# with the user passphrase
|
519
|
+
#
|
520
|
+
# Params: 'uuid' of the vault
|
521
|
+
# 'search' search queury as described in the wiki
|
522
|
+
#
|
523
|
+
# => Returns list of headers present in the vault
|
524
|
+
# according to the search queury
|
525
|
+
#
|
526
|
+
def access_headers(uuid, token, search = nil)
|
527
|
+
token.delete!("\n")
|
528
|
+
raise VaultNotAvailableError.new, "The vault you have requested data from is not currently active on this system." unless @@active_vaults["#{uuid}"]
|
529
|
+
|
530
|
+
raise UnknownTokenError.new, "The token you provided is unknown to this system. Access denied!" unless @@tokens[token]
|
531
|
+
|
532
|
+
raise UnautherisedTokenError.new, "The token you provided currently has no access to the desired vault. Access denied!" unless @@tokens[token].include?(uuid)
|
533
|
+
|
534
|
+
|
535
|
+
return @@active_vaults["#{uuid}"].list_headers(search)
|
536
|
+
end
|
537
|
+
|
538
|
+
|
539
|
+
# Request token for a vault permanently.
|
540
|
+
# Only used if @@no_token == false. Unlocks a vault as well
|
541
|
+
# with the user passphrase
|
542
|
+
#
|
543
|
+
# Params: 'uuid' of the vault
|
544
|
+
# 'file_name' file identifier to access
|
545
|
+
#
|
546
|
+
# => Returns contents (including headers) of a file either
|
547
|
+
# as it's current version or it's edit history.
|
548
|
+
#
|
549
|
+
def access_file(uuid, token, file_name, history = false)
|
550
|
+
token.delete!("\n")
|
551
|
+
raise VaultNotAvailableError.new, "The vault you have requested data from is not currently active on this system." unless @@active_vaults["#{uuid}"]
|
552
|
+
|
553
|
+
raise UnknownTokenError.new, "The token you provided is unknown to this system. Access denied!" unless @@tokens[token]
|
554
|
+
|
555
|
+
raise UnautherisedTokenError.new, "The token you provided currently has no access to the desired vault. Access denied!" unless @@tokens[token].include?(uuid)
|
556
|
+
return @@active_vaults["#{uuid}"].read_file(file_name, history)
|
557
|
+
end
|
558
|
+
|
559
|
+
# Request token for a vault permanently.
|
560
|
+
# Only used if @@no_token == false. Unlocks a vault as well
|
561
|
+
# with the user passphrase
|
562
|
+
#
|
563
|
+
# Params: 'uuid' of the vault
|
564
|
+
# 'file_name' file identifier to access
|
565
|
+
#
|
566
|
+
# => Returns contents of a file either as it's current
|
567
|
+
# version or it's edit history
|
568
|
+
#
|
569
|
+
def insert(uuid, token, file_name, data)
|
570
|
+
token.delete!("\n")
|
571
|
+
raise VaultNotAvailableError.new, "The vault you wish to insert data to is not currently active on this system." unless @@active_vaults["#{uuid}"]
|
572
|
+
|
573
|
+
raise UnknownTokenError.new, "The token you provided is unknown to this system. Access denied!" unless @@tokens[token]
|
574
|
+
|
575
|
+
raise UnautherisedTokenError.new, "The token you provided currently has no access to the desired vault. Access denied!" unless @@tokens[token].include?(uuid)
|
576
|
+
|
577
|
+
DaemonLogger.write("Writing data to #{uuid}", 'debug')
|
578
|
+
|
579
|
+
@@active_vaults["#{uuid}"].update(file_name, data)
|
580
|
+
end
|
581
|
+
|
582
|
+
# Request token for a vault permanently.
|
583
|
+
# Only used if @@no_token == false. Unlocks a vault as well
|
584
|
+
# with the user passphrase
|
585
|
+
#
|
586
|
+
# Params: 'uuid' of the vault
|
587
|
+
# 'file_name' file identifier to access
|
588
|
+
#
|
589
|
+
# => Returns contents of a file either as it's current
|
590
|
+
# version or it's edit history
|
591
|
+
#
|
592
|
+
def remove(uuid, token, file_name)
|
593
|
+
token.delete!("\n")
|
594
|
+
raise VaultNotAvailableError.new, "The vault you wish to insert data to is not currently active on this system." unless @@active_vaults["#{uuid}"]
|
595
|
+
|
596
|
+
raise UnknownTokenError.new, "The token you provided is unknown to this system. Access denied!" unless @@tokens[token]
|
597
|
+
|
598
|
+
raise UnautherisedTokenError.new, "The token you provided currently has no access to the desired vault. Access denied!" unless @@tokens[token].include?(uuid)
|
599
|
+
|
600
|
+
DaemonLogger.write("Writing data to #{uuid}", 'debug')
|
601
|
+
|
602
|
+
@@active_vaults["#{uuid}"].remove_file(file_name)
|
603
|
+
end
|
604
|
+
|
605
|
+
|
606
|
+
# Ends the exchange with a vault. Removes token from active vault record
|
607
|
+
#
|
608
|
+
def close_vault(uuid, token)
|
609
|
+
token.delete!("\n")
|
610
|
+
raise VaultNotAvailableError.new, "The vault you have requested data from is not currently active on this system." unless @@active_vaults["#{uuid}"]
|
611
|
+
|
612
|
+
raise UnknownTokenError.new, "The token you provided is unknown to this system. Access denied!" unless @@tokens[token]
|
613
|
+
|
614
|
+
raise UnautherisedTokenError.new, "The token you provided currently has no access to the desired vault. Access denied!" unless @@tokens[token].include?(uuid)
|
615
|
+
|
616
|
+
DaemonLogger.write("Closing vault with #{uuid}.", "debug")
|
617
|
+
|
618
|
+
# Close the vault
|
619
|
+
@@active_vaults["#{uuid}"].close
|
620
|
+
|
621
|
+
# Delete the vault from the active_vault record with UUID
|
622
|
+
@@active_vaults.delete("#{uuid}")
|
623
|
+
|
624
|
+
# TODO: Alert other applications
|
625
|
+
# TODO: Don't delete the token if it is being used to access
|
626
|
+
# other vaults on the system!
|
627
|
+
@@tokens.delete(token)
|
628
|
+
|
629
|
+
# Removes token from config
|
630
|
+
# TODO: FIX ME?!
|
631
|
+
@@config[:vaults]["#{uuid}"][:tokens].delete(token)
|
632
|
+
write_config
|
633
|
+
end
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
module Daemon
|
638
|
+
include Reedb
|
639
|
+
|
640
|
+
class << self
|
641
|
+
# Request token for a vault permanently.
|
642
|
+
# Only used if @@no_token == false. Unlocks a vault as well
|
643
|
+
# with the user passphrase
|
644
|
+
#
|
645
|
+
# Params: 'name' of the vault
|
646
|
+
# 'passphrase' to unlock
|
647
|
+
#
|
648
|
+
# => Returns token for vault
|
649
|
+
#
|
650
|
+
def request_token(uuid, passphrase, parmanent = false)
|
651
|
+
# If the vault is not currently open
|
652
|
+
unless @@active_vaults.include?(uuid)
|
653
|
+
unless @@config[:vaults][uuid]
|
654
|
+
DaemonLogger.write("The requested vault is unknown to this system. Aborting operation!", 'error')
|
655
|
+
raise VaultNotScopedError.new, "Requested vault #{uuid} is unknown to reedb. Has it been scoped before?"
|
656
|
+
end
|
657
|
+
# Continue
|
658
|
+
name = @@config[:vaults][uuid][:meta].name
|
659
|
+
path = @@config[:vaults][uuid][:meta].path
|
660
|
+
@@active_vaults[uuid] = ReeVault.new("#{name}", "#{path}", :auto).load(passphrase)
|
661
|
+
end
|
662
|
+
token = generate_token(uuid, path)
|
663
|
+
return token
|
664
|
+
end
|
665
|
+
|
666
|
+
# This function should be used by recurring applications that already own
|
667
|
+
# an authentication token for a vault.
|
668
|
+
#
|
669
|
+
def access_with_token(uuid, token, passphrase)
|
670
|
+
token.delete!("\n")
|
671
|
+
end
|
672
|
+
# Call this function to free a token and remove it from the access
|
673
|
+
# tree. This means that the vault it used to access are not removed or
|
674
|
+
# unloaded for other applications to use. But the token can no longer
|
675
|
+
# be used for file access.
|
676
|
+
#
|
677
|
+
def free_token(token)
|
678
|
+
token.delete!("\n")
|
679
|
+
|
680
|
+
# Throw a warning if the token isn't valid in the first place.
|
681
|
+
raise UnknownTokenError.new, "The token you provided is unknown to this system" unless @@tokens.include?(token)
|
682
|
+
|
683
|
+
@@tokens[token].each do |uuid|
|
684
|
+
@@config[:vaults]["#{uuid}"][:tokens].delete(token)
|
685
|
+
end
|
686
|
+
|
687
|
+
write_config
|
688
|
+
end
|
689
|
+
end #self class end
|
690
|
+
end # module Daemon end
|
691
|
+
end # Module Reedb end
|
692
|
+
|
693
|
+
passphrase = "1234567890123"
|
694
|
+
name = "default"
|
695
|
+
path = "/home/spacekookie/Desktop"
|
696
|
+
|
697
|
+
|
698
|
+
|
699
|
+
# name = "mega2"
|
700
|
+
# path = "/home/spacekookie"
|
701
|
+
# passphrase = "omg_awesome_sauce"
|
702
|
+
|
703
|
+
# Reedb::Core::init({:os=>:linux, :pw_length=>12})
|
704
|
+
#token = Reedb::Vault::create_vault(name, path, passphrase, :auto)
|
705
|
+
#puts token
|
706
|
+
# puts Reedb::generate_token("something", "blob")
|
707
|
+
|
708
|
+
# Reedb::Vault::scope_vault(name, path)
|
709
|
+
|
710
|
+
# puts Reedb::Vault::available_vaults
|
711
|
+
# Reedb::Vault::create_vault(name, path, user_pw)
|
712
|
+
|
713
|
+
# available = Reedb::Vault::available_vaults
|
714
|
+
# # puts "Available vaults: #{available}\n"
|
715
|
+
|
716
|
+
# puts Reedb::Config::Master::dump_config
|
717
|
+
# puts ""
|
718
|
+
# target = nil ; available.each { |uuid, meta| (target = uuid) if meta[:name] == "default" }
|
719
|
+
|
720
|
+
# puts "Target: #{target}"
|
721
|
+
|
722
|
+
# my_token = Reedb::Daemon::request_token(target, passphrase)
|
723
|
+
# puts "#{my_token}\n"
|
724
|
+
# search_qeuery = "tags=awsome#urls=www.lonelyrobot.io"
|
725
|
+
|
726
|
+
# headers = Reedb::Vault::access_headers(target, my_token, nil)
|
727
|
+
# print "#{headers}\n"
|
728
|
+
|
729
|
+
# Reedb::Vault::insert(target, my_token, "Lonely Robot", data1)
|
730
|
+
# Reedb::Vault::insert(target, my_token, "Lonely Robot", data2)
|
731
|
+
# Reedb::Vault::insert(target, my_token, "Lonely Robot", data3)
|
732
|
+
|
733
|
+
# puts Reedb::Vault::access_file(target, my_token, "Lonely Robot", true)
|
734
|
+
|
735
|
+
#headers = Reedb::Vault::access_headers(target, my_token)
|
736
|
+
#puts "Vault headers: #{headers}\n\n"
|
737
|
+
|
738
|
+
# Reedb::Vault::close_vault(target, my_token)
|
739
|
+
# Reedb::Core::terminate("aliens")
|