em-ftpd-memory 0.0.6 → 0.0.7
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 +28 -18
- data/em-ftpd-memory.gemspec +1 -1
- data/lib/em/ftpd/memory/authenticator.rb +49 -3
- data/lib/em/ftpd/memory/driver.rb +13 -11
- data/lib/em/ftpd/memory/filesystem.rb +33 -7
- data/test/helper.rb +1 -0
- data/test/test_authenticator.rb +20 -5
- data/test/test_ftpd-memory.rb +20 -8
- data/test/test_memory_filesystem.rb +13 -11
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c715cab895aa1f0db447b97d891e22c84cd52ae
|
4
|
+
data.tar.gz: 30665d3c15e7c72b9ad0f14cd0d621d2f2057e1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23d78443456ded147acc79c0c47063bc8bd295dedfc01c6099452e4bbfbfff4ecaafe416eb58ef106dd71542df51059553523205cb0ee828acfd22a7605b9aea
|
7
|
+
data.tar.gz: 4c4305f41b38491f6f206f253d9c2d7cb60a4c6fcff157ca974844b718bab40073ac19c2b4a01a289c1786c9b676bb470af80f05878c916aa0b201dee3132fbb
|
data/README.md
CHANGED
@@ -24,40 +24,50 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
options = {
|
26
26
|
"filesystem_name" => "boss",
|
27
|
-
"authentication_realm" => "georgia"
|
28
|
-
"pwalgo" => "otp",
|
29
|
-
|
27
|
+
"authentication_realm" => "georgia"
|
30
28
|
}
|
31
|
-
|
32
|
-
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"]
|
33
|
-
|
34
|
-
auth << User.new("test", "test1\ntest2\ntest3\ntest4\ntest5")
|
35
|
-
|
29
|
+
# set up the authentication
|
30
|
+
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"])
|
31
|
+
# add a test user
|
32
|
+
auth << User.new(:name => "test", :algo => "otp", :credential => "test1\ntest2\ntest3\ntest4\ntest5")
|
33
|
+
# add an anonymous user, note: algo defaults to none if there are no credentials are specified
|
34
|
+
auth << User.new(:name => "anonymous")
|
35
|
+
# create the filesystem
|
36
36
|
fs = FileSystem.getFileSystem(options["filesystem_name"])
|
37
|
-
|
37
|
+
# add a pub folder
|
38
38
|
fs.create_dir("/pub", 'root')
|
39
|
-
|
39
|
+
# add a file to the pub folder as root
|
40
40
|
fs.create_file("/pub/helper.rb", "test/helper.rb", 'root')
|
41
|
-
|
41
|
+
# chmod 755 /pub
|
42
42
|
fs.set_permissions("/pub", 'rwxr.xr.x', "root")
|
43
|
-
|
43
|
+
# create /uploads as root
|
44
44
|
fs.create_dir("/uploads", 'root')
|
45
|
-
|
45
|
+
# chmod 777 /uploads
|
46
46
|
fs.set_permissions("/uploads", "rwxrwxrwx", "root")
|
47
47
|
# create /users as root
|
48
48
|
fs.create_dir("/users", 'root')
|
49
|
-
|
49
|
+
# chmod 755 /users
|
50
50
|
fs.set_permissions("/users", "rwxr.xr.x", "root")
|
51
|
-
|
51
|
+
# create a personal directory for hiro, miyako, and pilar, (and add their test user)
|
52
52
|
["hiro", "miyako", "pilar"].each do |username|
|
53
|
+
# create a home directory
|
53
54
|
fs.create_dir("/users/#{username}", 'root')
|
54
|
-
|
55
|
+
# set the permissions so that no one else can access it
|
55
56
|
fs.set_permissions("/users/#{username}", "rwx......", "root")
|
56
|
-
|
57
|
+
# set the owner to the user
|
57
58
|
fs.set_owner("/users/#{username}", username, 'root')
|
58
|
-
|
59
|
+
# add the user to the authentication realm
|
60
|
+
auth << User.new(:name => username, :algo => "plain", :credential => username, :groups => ["testing"])
|
59
61
|
end
|
60
62
|
|
63
|
+
# since hiro, miyako, and pilar are all in the "testing" group, I can
|
64
|
+
# create a shared folder for them, but the "test" user won't be able to access
|
65
|
+
fs.create_dir("/shared", 'root')
|
66
|
+
fs.set_permissions("/shared", 'rwxr.xr.x', 'root')
|
67
|
+
fs.create_dir("/shared/testing", 'root')
|
68
|
+
fs.set_group("/shared/testing", 'testing', 'root')
|
69
|
+
fs.set_permissions("/shared/testing", 'rwxrwx...', 'root')
|
70
|
+
|
61
71
|
EM.run {
|
62
72
|
EventMachine::start_server("0.0.0.0", 2021, EM::FTPD::Server, EM::FTPD::Memory::Driver, options)
|
63
73
|
}
|
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.7"
|
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,26 +2,43 @@ require 'em-ftpd'
|
|
2
2
|
require 'digest/md5'
|
3
3
|
|
4
4
|
module EM::FTPD::Memory
|
5
|
-
class User < Struct.new(:name, :algo, :credential); end
|
6
5
|
class InvalidPasswordAlgorithmError < StandardError; end
|
7
6
|
class NoSuchUserError < StandardError; end
|
8
7
|
class InvalidCredentialError < StandardError; end
|
9
8
|
class ExpiredCredentialError < StandardError; end
|
10
9
|
class MalformatedCredentialError < StandardError; end
|
10
|
+
class ReplayCredentialError < StandardError; end
|
11
11
|
class NoFurtherCredentialsAvailable < StandardError; end
|
12
|
+
|
13
|
+
class TimedToken < Struct.new(:time, :token); end
|
14
|
+
|
15
|
+
class User
|
16
|
+
ATTRS = [:name, :algo, :credential, :groups]
|
17
|
+
attr_accessor(*ATTRS)
|
18
|
+
|
19
|
+
def initialize(options)
|
20
|
+
options.each do |attr, value|
|
21
|
+
self.send("#{attr}=", value)
|
22
|
+
end
|
23
|
+
@algo ||= (@credential) ? 'plain' : 'none'
|
24
|
+
@groups ||= []
|
25
|
+
raise ArgumentError.new("User requires a :name") unless @name
|
26
|
+
end
|
27
|
+
end
|
12
28
|
|
13
29
|
class Authenticator
|
14
30
|
@@realms = Hash.new
|
31
|
+
TOKEN_VALIDITY_PERIOD = 300
|
15
32
|
def self.getAuthenticatorByRealm(realm)
|
16
33
|
if @@realms[realm].nil?
|
17
34
|
@@realms[realm] = Authenticator.new
|
18
35
|
end
|
19
|
-
#puts "returning Authenticator of realm #{realm}"
|
20
36
|
@@realms[realm]
|
21
37
|
end
|
22
38
|
|
23
39
|
def initialize
|
24
40
|
@users = Hash.new
|
41
|
+
@used_tokens = Array.new
|
25
42
|
end
|
26
43
|
|
27
44
|
def <<(user)
|
@@ -42,6 +59,11 @@ module EM::FTPD::Memory
|
|
42
59
|
end
|
43
60
|
self.send(@users[username].algo, username, credential)
|
44
61
|
end
|
62
|
+
|
63
|
+
# this can be used for anonymous accounts
|
64
|
+
def none_authentication(username, credential)
|
65
|
+
return true
|
66
|
+
end
|
45
67
|
|
46
68
|
def plain_authentication(username, credential)
|
47
69
|
if @users[username].credential != credential
|
@@ -56,10 +78,13 @@ module EM::FTPD::Memory
|
|
56
78
|
if hash.nil? or hash.length != 32
|
57
79
|
raise MalformatedCredentialError.new
|
58
80
|
end
|
59
|
-
if (time.to_i - Time.now.to_i).abs >
|
81
|
+
if (time.to_i - Time.now.to_i).abs > TOKEN_VALIDITY_PERIOD
|
60
82
|
raise ExpiredCredentialError.new
|
61
83
|
else
|
62
84
|
if Digest::MD5.hexdigest("#{seed}:#{time}:#{@users[username].credential}") == hash
|
85
|
+
unless check_and_set_token(time.to_i, seed)
|
86
|
+
raise ReplayCredentialError.new
|
87
|
+
end
|
63
88
|
return true
|
64
89
|
else
|
65
90
|
raise InvalidCredentialError.new
|
@@ -80,5 +105,26 @@ module EM::FTPD::Memory
|
|
80
105
|
raise InvalidCredentialError.new
|
81
106
|
end
|
82
107
|
end
|
108
|
+
|
109
|
+
def groups(username)
|
110
|
+
if @users[username].nil?
|
111
|
+
raise NoSuchUserError.new
|
112
|
+
end
|
113
|
+
@users[username].groups
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def check_and_set_token(time, token)
|
119
|
+
# clean up stale tokens
|
120
|
+
@used_tokens.reject! {|t| t.time < Time.now.to_i - TOKEN_VALIDITY_PERIOD}
|
121
|
+
# check if token is replayed
|
122
|
+
if @used_tokens.find {|t| t.time == time and t.token == token}
|
123
|
+
return false
|
124
|
+
end
|
125
|
+
# add new token
|
126
|
+
@used_tokens << TimedToken.new(time, token)
|
127
|
+
true
|
128
|
+
end
|
83
129
|
end
|
84
130
|
end
|
@@ -4,8 +4,9 @@ module EM::FTPD::Memory
|
|
4
4
|
filesystem_name = options["filesystem_name"] || "default"
|
5
5
|
realm = options["authentication_realm"] || "default"
|
6
6
|
@fs = FileSystem.getFileSystem(filesystem_name)
|
7
|
-
@authenticator = Authenticator.getAuthenticatorByRealm(realm
|
7
|
+
@authenticator = Authenticator.getAuthenticatorByRealm(realm)
|
8
8
|
@authenticated_user = nil
|
9
|
+
@authenticated_user_groups = []
|
9
10
|
@server = Kernel.caller[0]
|
10
11
|
begin
|
11
12
|
$stderr.puts @server
|
@@ -16,17 +17,18 @@ module EM::FTPD::Memory
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def change_dir(path, &block)
|
19
|
-
yield @fs.change_dir(path, @authenticated_user)
|
20
|
+
yield @fs.change_dir(path, @authenticated_user, @authenticated_user_groups)
|
20
21
|
end
|
21
22
|
|
22
23
|
def dir_contents(path, &block)
|
23
|
-
yield @fs.list_files(path, @authenticated_user)
|
24
|
+
yield @fs.list_files(path, @authenticated_user, @authenticated_user_groups)
|
24
25
|
end
|
25
26
|
|
26
27
|
def authenticate(user, pass, &block)
|
27
28
|
begin
|
28
29
|
@authenticator.authenticate(user, pass)
|
29
30
|
@authenticated_user = user
|
31
|
+
@authenticated_user_groups = @authenticator.groups(user)
|
30
32
|
yield true
|
31
33
|
rescue Exception => e
|
32
34
|
#puts e.backtrace
|
@@ -35,35 +37,35 @@ module EM::FTPD::Memory
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def bytes(path, &block)
|
38
|
-
yield @fs.file_size(path, @authenticated_user)
|
40
|
+
yield @fs.file_size(path, @authenticated_user, @authenticated_user_groups)
|
39
41
|
end
|
40
42
|
|
41
43
|
def get_file(path, &block)
|
42
|
-
yield @fs.file_contents(path, @authenticated_user)
|
44
|
+
yield @fs.file_contents(path, @authenticated_user, @authenticated_user_groups)
|
43
45
|
end
|
44
46
|
|
45
47
|
def put_file(path, data, &block)
|
46
|
-
yield @fs.create_file(path, data, @authenticated_user)
|
48
|
+
yield @fs.create_file(path, data, @authenticated_user, @authenticated_user_groups)
|
47
49
|
end
|
48
50
|
|
49
51
|
def delete_file(path, &block)
|
50
|
-
yield @fs.delete_file(path, @authenticated_user)
|
52
|
+
yield @fs.delete_file(path, @authenticated_user, @authenticated_user_groups)
|
51
53
|
end
|
52
54
|
|
53
55
|
def delete_dir(path, &block)
|
54
|
-
yield @fs.delete_dir(path, @authenticated_user)
|
56
|
+
yield @fs.delete_dir(path, @authenticated_user, @authenticated_user_groups)
|
55
57
|
end
|
56
58
|
|
57
59
|
def rename(from, to, &block)
|
58
|
-
yield @fs.rename(from, to, @authenticated_user)
|
60
|
+
yield @fs.rename(from, to, @authenticated_user, @authenticated_user_groups)
|
59
61
|
end
|
60
62
|
|
61
63
|
def make_dir(path, &block)
|
62
|
-
yield @fs.create_dir(path, @authenticated_user)
|
64
|
+
yield @fs.create_dir(path, @authenticated_user, @authenticated_user_groups)
|
63
65
|
end
|
64
66
|
|
65
67
|
def mtime(path, &block)
|
66
|
-
yield @fs.modified_time(path, @authenticated_user)
|
68
|
+
yield @fs.modified_time(path, @authenticated_user, @authenticated_user_groups)
|
67
69
|
end
|
68
70
|
|
69
71
|
end
|
@@ -23,7 +23,6 @@ module EM::FTPD::Memory
|
|
23
23
|
if @@filesystems[name].nil?
|
24
24
|
@@filesystems[name] = FileSystem.new
|
25
25
|
end
|
26
|
-
#puts "returning FileSystem named #{name}"
|
27
26
|
return @@filesystems[name]
|
28
27
|
end
|
29
28
|
|
@@ -42,7 +41,14 @@ module EM::FTPD::Memory
|
|
42
41
|
|
43
42
|
|
44
43
|
def initialize
|
45
|
-
@root = MemoryDirectoryItem.new(
|
44
|
+
@root = MemoryDirectoryItem.new(
|
45
|
+
:name => '/',
|
46
|
+
:owner => 'root',
|
47
|
+
:group => 'root',
|
48
|
+
:directory => true,
|
49
|
+
:permissions => "rwxr.xr.x",
|
50
|
+
:contents => Hash.new
|
51
|
+
)
|
46
52
|
end
|
47
53
|
|
48
54
|
def exist?(path)
|
@@ -113,7 +119,14 @@ module EM::FTPD::Memory
|
|
113
119
|
item.contents = contents
|
114
120
|
item.size = contents.length
|
115
121
|
else # create new
|
116
|
-
dir.contents[basename] = MemoryDirectoryItem.new(
|
122
|
+
dir.contents[basename] = MemoryDirectoryItem.new(
|
123
|
+
:name => basename,
|
124
|
+
:owner => user,
|
125
|
+
:group => groups.first || "nogroup",
|
126
|
+
:size => contents.length,
|
127
|
+
:contents => contents,
|
128
|
+
:permissions => permissions
|
129
|
+
)
|
117
130
|
end
|
118
131
|
return true
|
119
132
|
else
|
@@ -154,7 +167,13 @@ module EM::FTPD::Memory
|
|
154
167
|
basename = File.basename(path)
|
155
168
|
parent = get_item(dirname)
|
156
169
|
if parent and parent.directory
|
157
|
-
parent.contents[basename] = MemoryDirectoryItem.new(
|
170
|
+
parent.contents[basename] = MemoryDirectoryItem.new(
|
171
|
+
:name => basename,
|
172
|
+
:directory => true,
|
173
|
+
:owner => user,
|
174
|
+
:group => groups.first || "nogroup",
|
175
|
+
:contents => Hash.new
|
176
|
+
)
|
158
177
|
return true
|
159
178
|
end
|
160
179
|
end
|
@@ -184,7 +203,14 @@ module EM::FTPD::Memory
|
|
184
203
|
end
|
185
204
|
|
186
205
|
def destroy
|
187
|
-
@root = MemoryDirectoryItem.new(
|
206
|
+
@root = MemoryDirectoryItem.new(
|
207
|
+
:name => '/',
|
208
|
+
:owner => 'root',
|
209
|
+
:group => 'root',
|
210
|
+
:directory => true,
|
211
|
+
:permissions => "rwxr.xr.x",
|
212
|
+
:contents => Hash.new
|
213
|
+
)
|
188
214
|
GC.start
|
189
215
|
end
|
190
216
|
|
@@ -212,9 +238,9 @@ module EM::FTPD::Memory
|
|
212
238
|
def set_group(path, group, user = nil, groups = [])
|
213
239
|
item = get_item(path)
|
214
240
|
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)
|
241
|
+
return false unless (user and user == "root") or groups.index(group)
|
217
242
|
item.group = group
|
243
|
+
true
|
218
244
|
end
|
219
245
|
|
220
246
|
#private
|
data/test/helper.rb
CHANGED
data/test/test_authenticator.rb
CHANGED
@@ -14,13 +14,13 @@ class TestAuthenticator < Minitest::Test
|
|
14
14
|
def test_invalid_pwalgo
|
15
15
|
assert_raises(InvalidPasswordAlgorithmError) do
|
16
16
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
17
|
-
auth << User.new("test", "nogood", "test")
|
17
|
+
auth << User.new(:name => "test", :algo => "nogood", :credential => "test")
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_plain_login
|
22
22
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
23
|
-
auth << User.new("test", "plain", "test")
|
23
|
+
auth << User.new(:name => "test", :algo => "plain", :credential => "test")
|
24
24
|
assert_raises(NoSuchUserError) do
|
25
25
|
auth.authenticate("jerk", "noway")
|
26
26
|
end
|
@@ -34,7 +34,7 @@ class TestAuthenticator < Minitest::Test
|
|
34
34
|
|
35
35
|
def test_time_based_login
|
36
36
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
37
|
-
auth << User.new("test", "timed_md5", "test")
|
37
|
+
auth << User.new(:name => "test", :algo => "timed_md5", :credential => "test")
|
38
38
|
assert_raises(NoSuchUserError) do
|
39
39
|
auth.authenticate("jerk", "noway")
|
40
40
|
end
|
@@ -59,7 +59,7 @@ class TestAuthenticator < Minitest::Test
|
|
59
59
|
time = Time.now.to_i
|
60
60
|
seed = "this is a random seed"
|
61
61
|
invalid_hash = Digest::MD5.hexdigest("#{seed}:#{time}:wrong")
|
62
|
-
invalid_cred = "#{seed}:#{time}:#{
|
62
|
+
invalid_cred = "#{seed}:#{time}:#{invalid_hash}"
|
63
63
|
|
64
64
|
assert_raises(InvalidCredentialError) do
|
65
65
|
auth.authenticate("test", invalid_cred)
|
@@ -71,11 +71,16 @@ class TestAuthenticator < Minitest::Test
|
|
71
71
|
valid_cred = "#{seed}:#{time}:#{valid_hash}"
|
72
72
|
|
73
73
|
assert(auth.authenticate("test", valid_cred))
|
74
|
+
|
75
|
+
assert_raises(ReplayCredentialError) do
|
76
|
+
auth.authenticate("test", valid_cred)
|
77
|
+
end
|
78
|
+
|
74
79
|
end
|
75
80
|
|
76
81
|
def test_otp_login
|
77
82
|
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
78
|
-
auth << User.new("test", "otp", "test1\ntest2\ntest3\ntest4\ntest5")
|
83
|
+
auth << User.new(:name => "test", :algo => "otp", :credential => "test1\ntest2\ntest3\ntest4\ntest5")
|
79
84
|
assert_raises(NoSuchUserError) do
|
80
85
|
auth.authenticate("jerk", "noway")
|
81
86
|
end
|
@@ -97,4 +102,14 @@ class TestAuthenticator < Minitest::Test
|
|
97
102
|
auth.authenticate("test", "test5")
|
98
103
|
end
|
99
104
|
end
|
105
|
+
|
106
|
+
def test_anonymous_login
|
107
|
+
auth = Authenticator.getAuthenticatorByRealm(__method__)
|
108
|
+
auth << User.new(:name => "anonymous")
|
109
|
+
assert_raises(NoSuchUserError) do
|
110
|
+
auth.authenticate("jerk", "noway")
|
111
|
+
end
|
112
|
+
|
113
|
+
assert(auth.authenticate("anonymous","test@example.com"))
|
114
|
+
end
|
100
115
|
end
|
data/test/test_ftpd-memory.rb
CHANGED
@@ -14,12 +14,18 @@ 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
|
+
}
|
17
21
|
# set up the authentication
|
18
|
-
auth = Authenticator.getAuthenticatorByRealm("
|
22
|
+
auth = Authenticator.getAuthenticatorByRealm(options["authentication_realm"])
|
19
23
|
# add a test user
|
20
|
-
auth << User.new("test", "otp", "test1\ntest2\ntest3\ntest4\ntest5")
|
24
|
+
auth << User.new(:name => "test", :algo => "otp", :credential => "test1\ntest2\ntest3\ntest4\ntest5")
|
25
|
+
# add an anonymous user, note: algo defaults to none if there are no credentials are specified
|
26
|
+
auth << User.new(:name => "anonymous")
|
21
27
|
# create the filesystem
|
22
|
-
fs = FileSystem.getFileSystem("
|
28
|
+
fs = FileSystem.getFileSystem(options["filesystem_name"])
|
23
29
|
# add a pub folder
|
24
30
|
fs.create_dir("/pub", 'root')
|
25
31
|
# add a file to the pub folder as root
|
@@ -36,18 +42,24 @@ class TestFTPDMemory < Minitest::Test
|
|
36
42
|
fs.set_permissions("/users", "rwxr.xr.x", "root")
|
37
43
|
# create a personal directory for hiro, miyako, and pilar, (and add their test user)
|
38
44
|
["hiro", "miyako", "pilar"].each do |username|
|
45
|
+
# create a home directory
|
39
46
|
fs.create_dir("/users/#{username}", 'root')
|
40
47
|
# set the permissions so that no one else can access it
|
41
48
|
fs.set_permissions("/users/#{username}", "rwx......", "root")
|
42
49
|
# set the owner to the user
|
43
50
|
fs.set_owner("/users/#{username}", username, 'root')
|
44
|
-
|
51
|
+
# add the user to the authentication realm
|
52
|
+
auth << User.new(:name => username, :algo => "plain", :credential => username, :groups => ["testing"])
|
45
53
|
end
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
# since hiro, miyako, and pilar are all in the "testing" group, I can
|
56
|
+
# create a shared folder for them, but the "test" user won't be able to access
|
57
|
+
fs.create_dir("/shared", 'root')
|
58
|
+
fs.set_permissions("/shared", 'rwxr.xr.x', 'root')
|
59
|
+
fs.create_dir("/shared/testing", 'root')
|
60
|
+
fs.set_group("/shared/testing", 'testing', 'root')
|
61
|
+
fs.set_permissions("/shared/testing", 'rwxrwx...', 'root')
|
62
|
+
|
51
63
|
EM.run {
|
52
64
|
EventMachine::start_server("0.0.0.0", 2021, EM::FTPD::Server, EM::FTPD::Memory::Driver, options)
|
53
65
|
EM::Timer.new(0.1) do
|
@@ -11,6 +11,8 @@ require_relative 'helper'
|
|
11
11
|
include EM::FTPD::Memory
|
12
12
|
|
13
13
|
class TestMemoryFilesystem < Minitest::Test
|
14
|
+
@@file_size = File.size("test/helper.rb")
|
15
|
+
|
14
16
|
def test_filesystem_instance_retrieval
|
15
17
|
fs = FileSystem.getFileSystem(__method__)
|
16
18
|
fs2 = FileSystem.getFileSystem(__method__)
|
@@ -28,7 +30,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
28
30
|
assert(fs.exist?("/helper.rb"))
|
29
31
|
refute(fs.is_dir?("/helper.rb"))
|
30
32
|
assert(fs.is_file?("/helper.rb"))
|
31
|
-
assert_equal(
|
33
|
+
assert_equal(@@file_size, fs.file_size("/helper.rb"))
|
32
34
|
FileSystem.destroyFileSystem(__method__)
|
33
35
|
end
|
34
36
|
|
@@ -39,7 +41,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
39
41
|
assert(fs.exist?("/helper.rb"))
|
40
42
|
refute(fs.is_dir?("/helper.rb"))
|
41
43
|
assert(fs.is_file?("/helper.rb"))
|
42
|
-
assert_equal(
|
44
|
+
assert_equal(@@file_size, fs.file_size("/helper.rb"))
|
43
45
|
assert(fs.delete_file("/helper.rb"))
|
44
46
|
refute(fs.exist?("/helper.rb"))
|
45
47
|
FileSystem.destroyFileSystem(__method__)
|
@@ -56,7 +58,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
56
58
|
|
57
59
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb"))
|
58
60
|
assert(fs.exist?("/pub/helper.rb"))
|
59
|
-
assert_equal(
|
61
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb"))
|
60
62
|
assert(fs.delete_file("/pub/helper.rb"))
|
61
63
|
refute(fs.exist?("/pub/helper.rb"))
|
62
64
|
FileSystem.destroyFileSystem(__method__)
|
@@ -72,7 +74,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
72
74
|
|
73
75
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb", "root"))
|
74
76
|
assert(fs.exist?("/pub/helper.rb"))
|
75
|
-
assert_equal(
|
77
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb", "root"))
|
76
78
|
refute(fs.delete_dir("/pub", "root"))
|
77
79
|
assert(fs.delete_file("/pub/helper.rb", "root"))
|
78
80
|
refute(fs.exist?("/pub/helper.rb"))
|
@@ -91,11 +93,11 @@ class TestMemoryFilesystem < Minitest::Test
|
|
91
93
|
|
92
94
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb"))
|
93
95
|
assert(fs.exist?("/pub/helper.rb"))
|
94
|
-
assert_equal(
|
96
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb"))
|
95
97
|
assert(fs.rename("/pub/helper.rb", "/pub/helper.txt"))
|
96
98
|
refute(fs.exist?("/pub/helper.rb"))
|
97
99
|
assert(fs.exist?("/pub/helper.txt"))
|
98
|
-
assert_equal(
|
100
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.txt"))
|
99
101
|
|
100
102
|
FileSystem.destroyFileSystem(__method__)
|
101
103
|
end
|
@@ -114,11 +116,11 @@ class TestMemoryFilesystem < Minitest::Test
|
|
114
116
|
|
115
117
|
assert(fs.create_file("/pub/helper.rb", "test/helper.rb"))
|
116
118
|
assert(fs.exist?("/pub/helper.rb"))
|
117
|
-
assert_equal(
|
119
|
+
assert_equal(@@file_size, fs.file_size("/pub/helper.rb"))
|
118
120
|
assert(fs.rename("/pub/helper.rb", "/pub2/helper.txt"))
|
119
121
|
refute(fs.exist?("/pub/helper.rb"))
|
120
122
|
assert(fs.exist?("/pub2/helper.txt"))
|
121
|
-
assert_equal(
|
123
|
+
assert_equal(@@file_size, fs.file_size("/pub2/helper.txt"))
|
122
124
|
|
123
125
|
FileSystem.destroyFileSystem(__method__)
|
124
126
|
end
|
@@ -138,7 +140,7 @@ class TestMemoryFilesystem < Minitest::Test
|
|
138
140
|
assert(fs.exist?("/pub3"))
|
139
141
|
refute(fs.is_dir?("/pub3"))
|
140
142
|
assert(fs.is_file?("/pub3"))
|
141
|
-
assert_equal(
|
143
|
+
assert_equal(@@file_size, fs.file_size("/pub3"))
|
142
144
|
|
143
145
|
refute(fs.rename("/pub", "/pub2"))
|
144
146
|
refute(fs.rename("/pub", "/pub3"))
|
@@ -176,14 +178,14 @@ class TestMemoryFilesystem < Minitest::Test
|
|
176
178
|
refute(fs.create_file("/pub/pub2/pub3/pub4/helper.rb", "test/helper.rb"))
|
177
179
|
assert(fs.create_file("/pub/pub2/pub3/pub4/helper.rb", "test/helper.rb", "root"))
|
178
180
|
refute(fs.file_size("/pub/pub2/pub3/pub4/helper.rb"))
|
179
|
-
assert_equal(
|
181
|
+
assert_equal(@@file_size, fs.file_size("/pub/pub2/pub3/pub4/helper.rb", "root"))
|
180
182
|
|
181
183
|
|
182
184
|
assert_equal(0, fs.list_files("/pub/pub2/pub3", "jem").length)
|
183
185
|
refute(fs.file_size("/pub/pub2/pub3/pub4/helper.rb", "jem"))
|
184
186
|
assert(fs.set_owner("/pub/pub2/pub3", "jem", "root"))
|
185
187
|
assert_equal(1, fs.list_files("/pub/pub2/pub3", "jem").length)
|
186
|
-
assert_equal(
|
188
|
+
assert_equal(@@file_size, fs.file_size("/pub/pub2/pub3/pub4/helper.rb", "jem"))
|
187
189
|
|
188
190
|
assert(fs.set_permissions("/pub/pub2", "rwx......", "root"))
|
189
191
|
# jem owns pub3, but should be denied since she can't traverse pub2
|
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.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chrislee35
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-ftpd
|
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
requirements: []
|
123
123
|
rubyforge_project:
|
124
|
-
rubygems_version: 2.
|
124
|
+
rubygems_version: 2.4.6
|
125
125
|
signing_key:
|
126
126
|
specification_version: 4
|
127
127
|
summary: Memory-based backing store for em-ftpd
|