em-ftpd-memory 0.0.5 → 0.0.6
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 +4 -4
- data/README.md +13 -1
- data/em-ftpd-memory.gemspec +1 -1
- data/lib/em/ftpd/memory/authenticator.rb +9 -10
- data/lib/em/ftpd/memory/filesystem.rb +44 -36
- data/test/test_authenticator.rb +8 -23
- data/test/test_ftpd-memory.rb +8 -10
- data/test/test_memory_filesystem.rb +8 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff070a000cded7f1c145979f7a4c42285e2c1075
|
4
|
+
data.tar.gz: f09bce2a5fdf592df680dd9c76512cfd0423940b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4384dee7ef945d52725be5732013ab356e54a7d1cf07833a971ffee061405864a1dce0e91c453e95f6643f96f7f2e07a9b96574c8edc072d12b6f2841c898914
|
7
|
+
data.tar.gz: 4b5da1d0cdbc510f8824043b7322a842df89117c98aabca89613809286e333562714adeacca34a4b505154ad79d6e3c352d4855ed6b80369b0c919ac873139b0
|
data/README.md
CHANGED
@@ -28,20 +28,32 @@ Or install it yourself as:
|
|
28
28
|
"pwalgo" => "otp",
|
29
29
|
|
30
30
|
}
|
31
|
+
# set up the authentication
|
31
32
|
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"], options)
|
33
|
+
# add a test user
|
32
34
|
auth << User.new("test", "test1\ntest2\ntest3\ntest4\ntest5")
|
35
|
+
# create the filesystem
|
33
36
|
fs = FileSystem.getFileSystem(options["filesystem_name"])
|
37
|
+
# add a pub folder
|
34
38
|
fs.create_dir("/pub", 'root')
|
39
|
+
# add a file to the pub folder as root
|
35
40
|
fs.create_file("/pub/helper.rb", "test/helper.rb", 'root')
|
41
|
+
# chmod 755 /pub
|
36
42
|
fs.set_permissions("/pub", 'rwxr.xr.x', "root")
|
43
|
+
# create /uploads as root
|
37
44
|
fs.create_dir("/uploads", 'root')
|
45
|
+
# chmod 777 /uploads
|
38
46
|
fs.set_permissions("/uploads", "rwxrwxrwx", "root")
|
39
|
-
|
47
|
+
# create /users as root
|
40
48
|
fs.create_dir("/users", 'root')
|
49
|
+
# chmod 755 /users
|
41
50
|
fs.set_permissions("/users", "rwxr.xr.x", "root")
|
51
|
+
# create a personal directory for hiro, miyako, and pilar, (and add their test user)
|
42
52
|
["hiro", "miyako", "pilar"].each do |username|
|
43
53
|
fs.create_dir("/users/#{username}", 'root')
|
54
|
+
# set the permissions so that no one else can access it
|
44
55
|
fs.set_permissions("/users/#{username}", "rwx......", "root")
|
56
|
+
# set the owner to the user
|
45
57
|
fs.set_owner("/users/#{username}", username, 'root')
|
46
58
|
auth << User.new(username, username)
|
47
59
|
end
|
data/em-ftpd-memory.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "em-ftpd-memory"
|
7
|
-
spec.version = "0.0.
|
7
|
+
spec.version = "0.0.6"
|
8
8
|
spec.authors = ["chrislee35"]
|
9
9
|
spec.email = ["rubygems@chrislee.dhs.org"]
|
10
10
|
spec.summary = %q{Memory-based backing store for em-ftpd}
|
@@ -2,7 +2,7 @@ require 'em-ftpd'
|
|
2
2
|
require 'digest/md5'
|
3
3
|
|
4
4
|
module EM::FTPD::Memory
|
5
|
-
class User < Struct.new(:name, :credential); end
|
5
|
+
class User < Struct.new(:name, :algo, :credential); end
|
6
6
|
class InvalidPasswordAlgorithmError < StandardError; end
|
7
7
|
class NoSuchUserError < StandardError; end
|
8
8
|
class InvalidCredentialError < StandardError; end
|
@@ -12,24 +12,23 @@ module EM::FTPD::Memory
|
|
12
12
|
|
13
13
|
class Authenticator
|
14
14
|
@@realms = Hash.new
|
15
|
-
def self.getAuthenticatorByRealm(realm
|
15
|
+
def self.getAuthenticatorByRealm(realm)
|
16
16
|
if @@realms[realm].nil?
|
17
|
-
@@realms[realm] = Authenticator.new
|
17
|
+
@@realms[realm] = Authenticator.new
|
18
18
|
end
|
19
19
|
#puts "returning Authenticator of realm #{realm}"
|
20
20
|
@@realms[realm]
|
21
21
|
end
|
22
22
|
|
23
|
-
def initialize
|
23
|
+
def initialize
|
24
24
|
@users = Hash.new
|
25
|
-
@pwalgo = options["pwalgo"] || "plain"
|
26
|
-
@pwalgo = "#{@pwalgo}_authentication".to_sym
|
27
|
-
unless self.respond_to?(@pwalgo)
|
28
|
-
raise InvalidPasswordAlgorithmError.new
|
29
|
-
end
|
30
25
|
end
|
31
26
|
|
32
27
|
def <<(user)
|
28
|
+
unless self.respond_to?("#{user.algo}_authentication".to_sym)
|
29
|
+
raise InvalidPasswordAlgorithmError.new
|
30
|
+
end
|
31
|
+
user.algo = "#{user.algo}_authentication".to_sym
|
33
32
|
@users[user.name] = user
|
34
33
|
end
|
35
34
|
|
@@ -41,7 +40,7 @@ module EM::FTPD::Memory
|
|
41
40
|
if @users[username].nil?
|
42
41
|
raise NoSuchUserError.new
|
43
42
|
end
|
44
|
-
self.send(@
|
43
|
+
self.send(@users[username].algo, username, credential)
|
45
44
|
end
|
46
45
|
|
47
46
|
def plain_authentication(username, credential)
|
@@ -41,10 +41,8 @@ module EM::FTPD::Memory
|
|
41
41
|
end
|
42
42
|
|
43
43
|
|
44
|
-
# TODO: support groups
|
45
|
-
|
46
44
|
def initialize
|
47
|
-
@root = MemoryDirectoryItem.new(:name => '/', :owner => 'root', :directory => true, :permissions => "rwxr.xr.x", :contents => Hash.new)
|
45
|
+
@root = MemoryDirectoryItem.new(:name => '/', :owner => 'root', :group => 'root', :directory => true, :permissions => "rwxr.xr.x", :contents => Hash.new)
|
48
46
|
end
|
49
47
|
|
50
48
|
def exist?(path)
|
@@ -68,13 +66,13 @@ module EM::FTPD::Memory
|
|
68
66
|
true
|
69
67
|
end
|
70
68
|
|
71
|
-
def change_dir(path, user = nil)
|
69
|
+
def change_dir(path, user = nil, groups = [])
|
72
70
|
item = get_item(path)
|
73
|
-
item.directory && use_allowed?(path, :list, user)
|
71
|
+
item.directory && use_allowed?(path, :list, user, groups)
|
74
72
|
end
|
75
73
|
|
76
|
-
def list_files(path, user = nil)
|
77
|
-
return [] unless use_allowed?(path, :list, user)
|
74
|
+
def list_files(path, user = nil, groups = [])
|
75
|
+
return [] unless use_allowed?(path, :list, user, groups)
|
78
76
|
item = get_item(path)
|
79
77
|
if item.directory
|
80
78
|
return item.contents.values
|
@@ -82,28 +80,28 @@ module EM::FTPD::Memory
|
|
82
80
|
return []
|
83
81
|
end
|
84
82
|
|
85
|
-
def file_size(path, user = nil)
|
86
|
-
return false unless use_allowed?(path, :size, user)
|
83
|
+
def file_size(path, user = nil, groups = [])
|
84
|
+
return false unless use_allowed?(path, :size, user, groups)
|
87
85
|
f = get_item(path)
|
88
86
|
return false unless f
|
89
87
|
f.size
|
90
88
|
end
|
91
89
|
|
92
|
-
def modified_time(path, user = nil)
|
93
|
-
return nil unless use_allowed?(path, :time, user)
|
90
|
+
def modified_time(path, user = nil, groups = [])
|
91
|
+
return nil unless use_allowed?(path, :time, user, groups)
|
94
92
|
f = get_item(path)
|
95
93
|
return nil unless f
|
96
94
|
f.time
|
97
95
|
end
|
98
96
|
|
99
|
-
def file_contents(path, user = nil)
|
100
|
-
return false unless use_allowed?(path, :read, user)
|
97
|
+
def file_contents(path, user = nil, groups = [])
|
98
|
+
return false unless use_allowed?(path, :read, user, groups)
|
101
99
|
item = get_item(path)
|
102
100
|
item.contents || false
|
103
101
|
end
|
104
102
|
|
105
|
-
def create_file(path, data, user = "nobody")
|
106
|
-
return false unless use_allowed?(path, :create, user)
|
103
|
+
def create_file(path, data, user = "nobody", groups = [])
|
104
|
+
return false unless use_allowed?(path, :create, user, groups)
|
107
105
|
dirname = File.dirname(path)
|
108
106
|
basename = File.basename(path)
|
109
107
|
dir = get_item(dirname)
|
@@ -123,8 +121,8 @@ module EM::FTPD::Memory
|
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
126
|
-
def delete_file(path, user = nil)
|
127
|
-
return false unless use_allowed?(path, :delete, user)
|
124
|
+
def delete_file(path, user = nil, groups = [])
|
125
|
+
return false unless use_allowed?(path, :delete, user, groups)
|
128
126
|
dirname = File.dirname(path)
|
129
127
|
basename = File.basename(path)
|
130
128
|
dir = get_item(dirname)
|
@@ -135,10 +133,10 @@ module EM::FTPD::Memory
|
|
135
133
|
false
|
136
134
|
end
|
137
135
|
|
138
|
-
def delete_dir(path, user = nil)
|
136
|
+
def delete_dir(path, user = nil, groups = [])
|
139
137
|
dir = get_item(path)
|
140
138
|
if dir and dir.directory and dir.contents.empty?
|
141
|
-
return false unless use_allowed?(path, :delete, user)
|
139
|
+
return false unless use_allowed?(path, :delete, user, groups)
|
142
140
|
dirname = File.dirname(path)
|
143
141
|
basename = File.basename(path)
|
144
142
|
parent = get_item(dirname)
|
@@ -148,10 +146,10 @@ module EM::FTPD::Memory
|
|
148
146
|
false
|
149
147
|
end
|
150
148
|
|
151
|
-
def create_dir(path, user = "nobody")
|
149
|
+
def create_dir(path, user = "nobody", groups = [])
|
152
150
|
dir = get_item(path)
|
153
151
|
if dir.nil?
|
154
|
-
return false unless use_allowed?(path, :create, user)
|
152
|
+
return false unless use_allowed?(path, :create, user, groups)
|
155
153
|
dirname = File.dirname(path)
|
156
154
|
basename = File.basename(path)
|
157
155
|
parent = get_item(dirname)
|
@@ -163,13 +161,13 @@ module EM::FTPD::Memory
|
|
163
161
|
return false
|
164
162
|
end
|
165
163
|
|
166
|
-
def rename(from, to, user = nil)
|
164
|
+
def rename(from, to, user = nil, groups = [])
|
167
165
|
titem = get_item(to)
|
168
166
|
return false if titem
|
169
167
|
fitem = get_item(from)
|
170
168
|
return false unless fitem
|
171
|
-
return false unless use_allowed?(from, :delete, user)
|
172
|
-
return false unless use_allowed?(to, :create, user)
|
169
|
+
return false unless use_allowed?(from, :delete, user, groups)
|
170
|
+
return false unless use_allowed?(to, :create, user, groups)
|
173
171
|
|
174
172
|
from_dirname = File.dirname(from)
|
175
173
|
from_basename = File.basename(from)
|
@@ -186,30 +184,38 @@ module EM::FTPD::Memory
|
|
186
184
|
end
|
187
185
|
|
188
186
|
def destroy
|
189
|
-
@root = MemoryDirectoryItem.new(:name => '/', :owner => 'root', :directory => true, :permissions => "rwxr.xr.x", :contents => Hash.new)
|
187
|
+
@root = MemoryDirectoryItem.new(:name => '/', :owner => 'root', :group => 'root', :directory => true, :permissions => "rwxr.xr.x", :contents => Hash.new)
|
190
188
|
GC.start
|
191
189
|
end
|
192
190
|
|
193
|
-
def set_permissions(path, permissions, user = nil)
|
191
|
+
def set_permissions(path, permissions, user = nil, groups = [])
|
194
192
|
item = get_item(path)
|
195
193
|
return false unless item
|
196
194
|
raise InvalidPermissionsError.new if permissions.nil?
|
197
195
|
raise InvalidPermissionsError.new(permissions.to_s) unless permissions.class == String
|
198
196
|
raise InvalidPermissionsError.new(permissions) unless permissions =~ /^[r\.][w\.][x\.][r\.][w\.][x\.][r\.][w\.][x\.]$/
|
199
|
-
if use_allowed?(path, :chmod, user)
|
197
|
+
if use_allowed?(path, :chmod, user, groups)
|
200
198
|
item.permissions = permissions
|
201
199
|
return true
|
202
200
|
end
|
203
201
|
false
|
204
202
|
end
|
205
203
|
|
206
|
-
def set_owner(path, owner, user = nil)
|
204
|
+
def set_owner(path, owner, user = nil, groups = [])
|
207
205
|
item = get_item(path)
|
208
206
|
return false unless item and owner and owner.class == String
|
209
207
|
return false unless user and user == "root"
|
210
208
|
item.owner = owner
|
211
209
|
true
|
212
210
|
end
|
211
|
+
|
212
|
+
def set_group(path, group, user = nil, groups = [])
|
213
|
+
item = get_item(path)
|
214
|
+
return false unless item and group and group.class == String
|
215
|
+
return false unless user and user == "root"
|
216
|
+
return false unless groups.index(group)
|
217
|
+
item.group = group
|
218
|
+
end
|
213
219
|
|
214
220
|
#private
|
215
221
|
|
@@ -224,7 +230,7 @@ module EM::FTPD::Memory
|
|
224
230
|
cur
|
225
231
|
end
|
226
232
|
|
227
|
-
def use_allowed?(path, use, username)
|
233
|
+
def use_allowed?(path, use, username, groups = [])
|
228
234
|
return true if username == 'root'
|
229
235
|
|
230
236
|
dirname = File.dirname(path)
|
@@ -234,17 +240,17 @@ module EM::FTPD::Memory
|
|
234
240
|
dirname.split(/\//).each do |dir|
|
235
241
|
next if dir == '/'
|
236
242
|
cwd << dir
|
237
|
-
return false unless allowed?(cwd, "rx", username)
|
243
|
+
return false unless allowed?(cwd, "rx", username, groups)
|
238
244
|
cwd << '/'
|
239
245
|
end
|
240
246
|
|
241
247
|
case use
|
242
248
|
when :read
|
243
|
-
return allowed?(path, 'r', username)
|
249
|
+
return allowed?(path, 'r', username, groups)
|
244
250
|
when :write
|
245
|
-
return allowed?(path, 'w', username)
|
251
|
+
return allowed?(path, 'w', username, groups)
|
246
252
|
when :list
|
247
|
-
return allowed?(path, 'rx', username)
|
253
|
+
return allowed?(path, 'rx', username, groups)
|
248
254
|
when :size
|
249
255
|
return true # since we've already checked everything
|
250
256
|
when :time
|
@@ -253,15 +259,15 @@ module EM::FTPD::Memory
|
|
253
259
|
item = get_item(path)
|
254
260
|
return item.owner == username
|
255
261
|
when :delete
|
256
|
-
return allowed?(dirname, "rwx", username)
|
262
|
+
return allowed?(dirname, "rwx", username, groups)
|
257
263
|
when :create
|
258
|
-
return allowed?(dirname, "rwx", username)
|
264
|
+
return allowed?(dirname, "rwx", username, groups)
|
259
265
|
else
|
260
266
|
return false
|
261
267
|
end
|
262
268
|
end
|
263
269
|
|
264
|
-
def allowed?(path, required_permissions, username)
|
270
|
+
def allowed?(path, required_permissions, username, groups)
|
265
271
|
item = get_item(path)
|
266
272
|
return false unless item
|
267
273
|
permissions = item.permissions || 'rwxrwxrwx'
|
@@ -269,6 +275,8 @@ module EM::FTPD::Memory
|
|
269
275
|
perms = permissions[6,3]
|
270
276
|
elsif item.owner == username
|
271
277
|
perms = permissions[0,3]
|
278
|
+
elsif groups.index(item.group)
|
279
|
+
perms = permissions[3,3]
|
272
280
|
else
|
273
281
|
perms = permissions[6,3]
|
274
282
|
end
|
data/test/test_authenticator.rb
CHANGED
@@ -12,22 +12,15 @@ include EM::FTPD::Memory
|
|
12
12
|
|
13
13
|
class TestAuthenticator < Minitest::Test
|
14
14
|
def test_invalid_pwalgo
|
15
|
-
options = {
|
16
|
-
"pwalgo" => "nogood",
|
17
|
-
"authentication_realm" => "invalid"
|
18
|
-
}
|
19
15
|
assert_raises(InvalidPasswordAlgorithmError) do
|
20
|
-
Authenticator.getAuthenticatorByRealm(
|
16
|
+
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
17
|
+
auth << User.new("test", "nogood", "test")
|
21
18
|
end
|
22
19
|
end
|
23
20
|
|
24
21
|
def test_plain_login
|
25
|
-
|
26
|
-
|
27
|
-
"authentication_realm" => "plain"
|
28
|
-
}
|
29
|
-
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"], options)
|
30
|
-
auth << User.new("test", "test")
|
22
|
+
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
23
|
+
auth << User.new("test", "plain", "test")
|
31
24
|
assert_raises(NoSuchUserError) do
|
32
25
|
auth.authenticate("jerk", "noway")
|
33
26
|
end
|
@@ -40,12 +33,8 @@ class TestAuthenticator < Minitest::Test
|
|
40
33
|
end
|
41
34
|
|
42
35
|
def test_time_based_login
|
43
|
-
|
44
|
-
|
45
|
-
"authentication_realm" => "time_based"
|
46
|
-
}
|
47
|
-
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"], options)
|
48
|
-
auth << User.new("test", "test")
|
36
|
+
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
37
|
+
auth << User.new("test", "timed_md5", "test")
|
49
38
|
assert_raises(NoSuchUserError) do
|
50
39
|
auth.authenticate("jerk", "noway")
|
51
40
|
end
|
@@ -85,12 +74,8 @@ class TestAuthenticator < Minitest::Test
|
|
85
74
|
end
|
86
75
|
|
87
76
|
def test_otp_login
|
88
|
-
|
89
|
-
|
90
|
-
"authentication_realm" => "otp"
|
91
|
-
}
|
92
|
-
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"], options)
|
93
|
-
auth << User.new("test", "test1\ntest2\ntest3\ntest4\ntest5")
|
77
|
+
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
78
|
+
auth << User.new("test", "otp", "test1\ntest2\ntest3\ntest4\ntest5")
|
94
79
|
assert_raises(NoSuchUserError) do
|
95
80
|
auth.authenticate("jerk", "noway")
|
96
81
|
end
|
data/test/test_ftpd-memory.rb
CHANGED
@@ -14,18 +14,12 @@ include EM::FTPD::Memory
|
|
14
14
|
|
15
15
|
class TestFTPDMemory < Minitest::Test
|
16
16
|
def test_example
|
17
|
-
options = {
|
18
|
-
"filesystem_name" => "boss",
|
19
|
-
"authentication_realm" => "georgia",
|
20
|
-
"pwalgo" => "otp",
|
21
|
-
|
22
|
-
}
|
23
17
|
# set up the authentication
|
24
|
-
auth = Authenticator.getAuthenticatorByRealm(
|
18
|
+
auth = Authenticator.getAuthenticatorByRealm("georgia")
|
25
19
|
# add a test user
|
26
|
-
auth << User.new("test", "test1\ntest2\ntest3\ntest4\ntest5")
|
20
|
+
auth << User.new("test", "otp", "test1\ntest2\ntest3\ntest4\ntest5")
|
27
21
|
# create the filesystem
|
28
|
-
fs = FileSystem.getFileSystem(
|
22
|
+
fs = FileSystem.getFileSystem("boss")
|
29
23
|
# add a pub folder
|
30
24
|
fs.create_dir("/pub", 'root')
|
31
25
|
# add a file to the pub folder as root
|
@@ -47,9 +41,13 @@ class TestFTPDMemory < Minitest::Test
|
|
47
41
|
fs.set_permissions("/users/#{username}", "rwx......", "root")
|
48
42
|
# set the owner to the user
|
49
43
|
fs.set_owner("/users/#{username}", username, 'root')
|
50
|
-
auth << User.new(username, username)
|
44
|
+
auth << User.new(username, "plain", username)
|
51
45
|
end
|
52
46
|
|
47
|
+
options = {
|
48
|
+
"filesystem_name" => "boss",
|
49
|
+
"authentication_realm" => "georgia"
|
50
|
+
}
|
53
51
|
EM.run {
|
54
52
|
EventMachine::start_server("0.0.0.0", 2021, EM::FTPD::Server, EM::FTPD::Memory::Driver, options)
|
55
53
|
EM::Timer.new(0.1) do
|
@@ -190,6 +190,14 @@ class TestMemoryFilesystem < Minitest::Test
|
|
190
190
|
refute(fs.set_permissions("/pub/pub2/pub3", "rwx......", "jem"))
|
191
191
|
assert(fs.set_permissions("/pub/pub2", "rwxr.xr.x", "root"))
|
192
192
|
assert(fs.set_permissions("/pub/pub2/pub3", "rwx......", "jem"))
|
193
|
+
|
194
|
+
assert(fs.create_dir("/group_test", "root"))
|
195
|
+
assert(fs.set_group("/group_test", "test", "root", ["test"]))
|
196
|
+
assert(fs.set_permissions("/group_test", "rwxr.x...", "root"))
|
197
|
+
assert(fs.create_file("/group_test/test", "test/helper.rb", "root"))
|
198
|
+
assert_equal(0, fs.list_files("/group_test", "jem", ["nottest"]).length)
|
199
|
+
assert_equal(1, fs.list_files("/group_test", "jem", ["test", "other", "punkbands"]).length)
|
200
|
+
|
193
201
|
end
|
194
202
|
|
195
203
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-ftpd-memory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chrislee35
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-ftpd
|