em-ftpd-memory 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|