shikashi 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ 0.4.0 Removed evalmimic dependency
2
+
3
+ Implemented sugar syntax for Sandbox and Privileges methods (see documentation)
4
+
5
+ Added control over READ access to constants
6
+
7
+ Added control over READ access to global variables
8
+
1
9
  0.3.1 Fixed package info
2
10
 
3
11
  0.3.0 Added enclosure by base_namespace parameter (see examples)
@@ -5,6 +13,8 @@
5
13
  shikashi HookHandler opened to allow use it in nested hook handlers
6
14
 
7
15
  Added restriction to avoid the system calls when using %x[] and ``
16
+
17
+ 0.2.0 shikashi HookHandler opened to allow use it in nested hook handlers
8
18
 
9
19
  0.2.0 Added control over the access to constants and global variables (See documentation)
10
20
 
data/Rakefile CHANGED
@@ -6,15 +6,14 @@ require 'rake/gempackagetask'
6
6
 
7
7
  spec = Gem::Specification.new do |s|
8
8
  s.name = 'shikashi'
9
- s.version = '0.3.1'
9
+ s.version = '0.4.0'
10
10
  s.author = 'Dario Seminara'
11
11
  s.email = 'robertodarioseminara@gmail.com'
12
12
  s.platform = Gem::Platform::RUBY
13
13
  s.summary = 'shikashi is a ruby sandbox that permits the execution of "unprivileged" scripts by defining the permitted methods and constants the scripts can invoke with a white list logic'
14
14
  s.homepage = "http://github.com/tario/shikashi"
15
- s.add_dependency "evalhook", ">= 0.2.0"
15
+ s.add_dependency "evalhook", ">= 0.4.0"
16
16
  s.add_dependency "getsource", ">= 0.1.0"
17
- s.add_dependency "evalmimic", ">= 0.1.0"
18
17
  s.has_rdoc = true
19
18
  s.extra_rdoc_files = [ 'README' ]
20
19
  # s.rdoc_options << '--main' << 'README'
@@ -6,10 +6,6 @@ require "shikashi"
6
6
  include Shikashi
7
7
 
8
8
  s = Sandbox.new
9
- priv = Privileges.new
10
-
11
- # allow execution of print
12
- priv.allow_method :print
13
9
 
14
10
  class X
15
11
  def foo
@@ -25,12 +21,14 @@ class X
25
21
  system("echo privileged operation > " + out)
26
22
  end
27
23
  end
28
- # allow method new of class X
29
- priv.object(X).allow :new
30
24
 
31
- # allow instance methods of X. Note that the method privileged_operations is not allowed
32
- priv.instances_of(X).allow :foo, :bar
33
25
 
26
+ priv = Privileges.
27
+ allow_method(:print). # allow execution of print
28
+ object(X).allow(:new). # allow method new of class X
29
+ instances_of(X).allow(:foo, :bar). # allow instance methods of X. Note that the method privileged_operations is not allowed
30
+ allow_const_read("X","SecurityError") # allow the access of X constant
31
+
34
32
  #inside the sandbox, only can use method foo on main and method times on instances of Fixnum
35
33
  s.run(priv, '
36
34
  x = X.new
@@ -5,15 +5,12 @@ require "shikashi"
5
5
 
6
6
  include Shikashi
7
7
 
8
- s = Sandbox.new
9
- priv = Privileges.new
10
-
11
- priv.allow_method :print
12
- priv.allow_global :$a
13
-
14
- s.run(priv, '
8
+ priv = Privileges.allow_method(:print).allow_global_write(:$a)
9
+ Sandbox.run(priv,
10
+ '
15
11
  $a = 9
16
12
  print "assigned 9 to $a\n"
17
- ')
13
+ '
14
+ )
18
15
 
19
16
  p $a
@@ -3,13 +3,11 @@ require "shikashi"
3
3
 
4
4
  include Shikashi
5
5
 
6
- s = Sandbox.new
7
- priv = Privileges.new
6
+ priv = Privileges.
7
+ allow_method(:print).
8
+ allow_const_write("Object::A")
8
9
 
9
- priv.allow_method :print
10
- priv.allow_const "Object::A"
11
-
12
- s.run(priv, '
10
+ Sandbox.run(priv, '
13
11
  print "assigned 8 to Object::A\n"
14
12
  A = 8
15
13
  ')
@@ -12,17 +12,13 @@ class X
12
12
  end
13
13
  end
14
14
 
15
- s = Sandbox.new
16
- priv = Privileges.new
17
- priv.allow_method :print
18
-
19
- s.run( "
15
+ Sandbox.new.run( "
20
16
  class ::X
21
17
  def foo
22
18
  print \"foo defined inside the sandbox\\n\"
23
19
  end
24
20
  end
25
- ", priv, :base_namespace => SandboxModule)
21
+ ", Privileges.allow_method(:print), :base_namespace => SandboxModule)
26
22
 
27
23
 
28
24
  x = X.new # X class is not affected by the sandbox (The X Class defined in the sandbox is SandboxModule::X)
@@ -40,7 +40,8 @@ public
40
40
 
41
41
  # Used in Privileges to store information about specified method permissions
42
42
  class AllowedMethods
43
- def initialize
43
+ def initialize(privileges = nil)
44
+ @privileges = privileges
44
45
  @allowed_methods = Array.new
45
46
  @redirect_hash = Hash.new
46
47
  @all = false
@@ -78,11 +79,15 @@ public
78
79
  method_names.each do |mn|
79
80
  @allowed_methods << mn
80
81
  end
82
+
83
+ @privileges
81
84
  end
82
85
 
83
86
  #Specifies that any method is allowed
84
87
  def allow_all
85
88
  @all = true
89
+
90
+ @privileges
86
91
  end
87
92
 
88
93
  end
@@ -94,15 +99,17 @@ public
94
99
  @allowed_instances = Hash.new
95
100
  @allowed_methods = Array.new
96
101
  @allowed_klass_methods = Hash.new
97
- @allowed_globals = Array.new
98
- @allowed_consts = Array.new
102
+ @allowed_read_globals = Array.new
103
+ @allowed_read_consts = Array.new
104
+ @allowed_write_globals = Array.new
105
+ @allowed_write_consts = Array.new
99
106
  end
100
107
 
101
108
  private
102
109
  def hash_entry(hash, key)
103
110
  tmp = hash[key]
104
111
  unless tmp
105
- tmp = AllowedMethods.new
112
+ tmp = AllowedMethods.new(self)
106
113
  hash[key] = tmp
107
114
  end
108
115
  tmp
@@ -168,7 +175,8 @@ public
168
175
  #
169
176
 
170
177
  def allow_method(method_name)
171
- @allowed_methods << method_name
178
+ @allowed_methods << method_name.to_sym
179
+ self
172
180
  end
173
181
 
174
182
  def allow?(klass, recv, method_name, method_id)
@@ -254,15 +262,23 @@ public
254
262
  @xstr_allowed
255
263
  end
256
264
 
257
- def global_allowed?(varname)
258
- @allowed_globals.include? varname
265
+ def global_read_allowed?(varname)
266
+ @allowed_read_globals.include? varname
267
+ end
268
+
269
+ def global_write_allowed?(varname)
270
+ @allowed_write_globals.include? varname
259
271
  end
260
272
 
261
- def const_allowed?(varname)
262
- @allowed_consts.include? varname
273
+ def const_read_allowed?(varname)
274
+ @allowed_read_consts.include? varname
263
275
  end
264
276
 
265
- # defines the permissions needed to execute system calls from the script
277
+ def const_write_allowed?(varname)
278
+ @allowed_write_consts.include? varname
279
+ end
280
+
281
+ # Enables the permissions needed to execute system calls from the script
266
282
  #
267
283
  # Example:
268
284
  #
@@ -274,11 +290,19 @@ public
274
290
  # s.run(priv, '
275
291
  # %x[ls -l]
276
292
  # ')
293
+ #
294
+ #
295
+ # Example 2:
296
+ #
297
+ # Sandbox.run('%x[ls -l]', Privileges.allow_xstr)
298
+ #
277
299
  def allow_xstr
278
300
  @xstr_allowed = true
301
+
302
+ self
279
303
  end
280
304
 
281
- # defines the permissions needed to create or change a global variable
305
+ # Enables the permissions needed to read one or more global variables
282
306
  #
283
307
  # Example:
284
308
  #
@@ -286,7 +310,38 @@ public
286
310
  # priv = Privileges.new
287
311
  #
288
312
  # priv.allow_method :print
289
- # priv.allow_global :$a
313
+ # priv.allow_global_read :$a
314
+ #
315
+ # $a = 9
316
+ #
317
+ # s.run(priv, '
318
+ # print "$a value:", $a, "s\n"
319
+ # ')
320
+ #
321
+ # Example 2
322
+ #
323
+ # Sandbox.run('
324
+ # print "$a value:", $a, "s\n"
325
+ # print "$b value:", $b, "s\n"
326
+ # ', Privileges.allow_global_read(:$a,:$b) )
327
+ #
328
+ def allow_global_read( *varnames )
329
+ varnames.each do |varname|
330
+ @allowed_read_globals << varname.to_sym
331
+ end
332
+
333
+ self
334
+ end
335
+
336
+ # Enables the permissions needed to create or change one or more global variables
337
+ #
338
+ # Example:
339
+ #
340
+ # s = Sandbox.new
341
+ # priv = Privileges.new
342
+ #
343
+ # priv.allow_method :print
344
+ # priv.allow_global_write :$a
290
345
  #
291
346
  # s.run(priv, '
292
347
  # $a = 9
@@ -295,18 +350,23 @@ public
295
350
  #
296
351
  # p $a
297
352
  #
298
- def allow_global( varname )
299
- @allowed_globals << varname
353
+ def allow_global_write( *varnames )
354
+ varnames.each do |varname|
355
+ @allowed_write_globals << varname.to_sym
356
+ end
357
+
358
+ self
300
359
  end
301
360
 
302
- # defines the permissions needed to create or change a const
361
+
362
+ # Enables the permissions needed to create or change one or more constants
303
363
  #
304
364
  # Example:
305
365
  # s = Sandbox.new
306
366
  # priv = Privileges.new
307
367
  #
308
368
  # priv.allow_method :print
309
- # priv.allow_const "Object::A"
369
+ # priv.allow_const_write "Object::A"
310
370
  #
311
371
  # s.run(priv, '
312
372
  # print "assigned 8 to Object::A\n"
@@ -315,10 +375,43 @@ public
315
375
  #
316
376
  # p A
317
377
 
318
- def allow_const( varname )
319
- @allowed_consts << varname
378
+ def allow_const_write( *varnames )
379
+ varnames.each do |varname|
380
+ @allowed_write_consts << varname.to_s
381
+ end
382
+ self
383
+ end
384
+
385
+ # Enables the permissions needed to read one or more constants
386
+ #
387
+ # Example:
388
+ # s = Sandbox.new
389
+ # priv = Privileges.new
390
+ #
391
+ # priv.allow_method :print
392
+ # priv.allow_const_read "Object::A"
393
+ #
394
+ # A = 8
395
+ # s.run(priv, '
396
+ # print "assigned Object::A:", A,"\n"
397
+ # ')
398
+ #
399
+ def allow_const_read( *varnames )
400
+ varnames.each do |varname|
401
+ @allowed_read_consts << varname.to_s
402
+ end
403
+
404
+ self
320
405
  end
321
406
 
407
+
408
+ class << self
409
+ (Shikashi::Privileges.instance_methods - Object.instance_methods).each do |mname|
410
+ define_method(mname) do |*args|
411
+ Shikashi::Privileges.new.send(mname, *args)
412
+ end
413
+ end
414
+ end
322
415
  end
323
416
 
324
417
  end
@@ -24,7 +24,6 @@ require "shikashi/privileges"
24
24
  require "shikashi/pick_argument"
25
25
  require "getsource"
26
26
  require "timeout"
27
- require "evalmimic"
28
27
 
29
28
  module Shikashi
30
29
 
@@ -71,6 +70,13 @@ module Shikashi
71
70
  attr_reader :hook_handler
72
71
 
73
72
  #
73
+ # Same as Sandbox.new.run
74
+ #
75
+
76
+ def self.run(*args)
77
+ Sandbox.new.run(Shikashi.global_binding, *args)
78
+ end
79
+ #
74
80
  # Generate a random source file name for the sandbox, used internally
75
81
  #
76
82
 
@@ -113,7 +119,7 @@ module Shikashi
113
119
 
114
120
  privileges = sandbox.privileges[source]
115
121
  if privileges
116
- unless privileges.global_allowed? global_id
122
+ unless privileges.global_write_allowed? global_id
117
123
  raise SecurityError.new("Cannot assign global variable #{global_id}")
118
124
  end
119
125
  end
@@ -121,13 +127,45 @@ module Shikashi
121
127
  nil
122
128
  end
123
129
 
130
+ def handle_gvar(global_id)
131
+ source = get_caller
132
+ privileges = sandbox.privileges[source]
133
+ if privileges
134
+ unless privileges.global_read_allowed? global_id
135
+ raise SecurityError, "cannot access global variable #{global_id}"
136
+ end
137
+ end
138
+
139
+ nil
140
+ end
141
+
142
+ def handle_const(name)
143
+ source = get_caller
144
+ privileges = sandbox.privileges[source]
145
+ if privileges
146
+ unless sandbox.base_namespace.constants.include? name
147
+ unless privileges.const_read_allowed? name.to_s
148
+ raise SecurityError, "cannot access constant #{name}"
149
+ end
150
+ end
151
+ end
152
+
153
+ const_value(sandbox.base_namespace.const_get(name))
154
+ end
155
+
124
156
  def handle_cdecl(klass, const_id, value)
125
157
  source = get_caller
126
158
 
127
159
  privileges = sandbox.privileges[source]
128
160
  if privileges
129
- unless privileges.const_allowed? "#{klass}::#{const_id}"
130
- raise SecurityError.new("Cannot assign const #{klass}::#{const_id}")
161
+ unless privileges.const_write_allowed? "#{klass}::#{const_id}"
162
+ if (klass == Object)
163
+ unless privileges.const_write_allowed? const_id.to_s
164
+ raise SecurityError.new("Cannot assign const #{const_id}")
165
+ end
166
+ else
167
+ raise SecurityError.new("Cannot assign const #{klass}::#{const_id}")
168
+ end
131
169
  end
132
170
  end
133
171
 
@@ -255,19 +293,18 @@ module Shikashi
255
293
  #
256
294
  #
257
295
  def run(*args)
258
- end
259
-
260
- define_eval_method :run
261
- def internal_eval(b_, args)
262
-
263
296
  newargs = Array.new
264
297
 
265
298
  timeout = args.pick(:timeout) do nil end
266
299
  privileges_ = args.pick(Privileges,:privileges) do Privileges.new end
267
300
  code = args.pick(String,:code)
268
- binding_ = args.pick(Binding,:binding) do b_ end
301
+
269
302
  source = args.pick(:source) do nil end
270
303
  base_namespace = args.pick(:base_namespace) do create_adhoc_base_namespace end
304
+
305
+ binding_ = args.pick(Binding,:binding) do
306
+ nil
307
+ end
271
308
  @base_namespace = base_namespace
272
309
  no_base_namespace = args.pick(:no_base_namespace) do false end
273
310
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shikashi
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 1
10
- version: 0.3.1
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dario Seminara
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-22 00:00:00 -03:00
18
+ date: 2011-04-28 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,12 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- hash: 23
29
+ hash: 15
30
30
  segments:
31
31
  - 0
32
- - 2
32
+ - 4
33
33
  - 0
34
- version: 0.2.0
34
+ version: 0.4.0
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -50,22 +50,6 @@ dependencies:
50
50
  version: 0.1.0
51
51
  type: :runtime
52
52
  version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: evalmimic
55
- prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 27
62
- segments:
63
- - 0
64
- - 1
65
- - 0
66
- version: 0.1.0
67
- type: :runtime
68
- version_requirements: *id003
69
53
  description:
70
54
  email: robertodarioseminara@gmail.com
71
55
  executables: []