Hiding modules

T

Tommy Trojan

Hi,

I have a custom application in which I have a Python interpreter embedded.
Everything works really well and Python is taking over bigger and bigger
chunks of the hosting application (it's spreading like a cancer :). My
users have direct access to the interpreter through a console window. So
they can run pretty much any code they like. Now I have some modules that I
use in my code and that I don't want my users to access. Is there anything
that can be done to import modules conditionally?
I guess I could just check for import statements or write an __import__
hook, however, I want my code still to be able to access the modules in
question.
Any ideas?

Thanks,
T
 
M

Miki Tebeka

Hello Tommy,

Is there anything that can be done to import modules conditionally?
Any ideas?
Writing a custom REPL (read-eval-print-loop) should be easy enough:
import re
split = re.compile("\s+").split

forbidden = ("os", "sys")

def repl():
while 1:
s = raw_input(">>> ").strip()
ok = 1
if s.startswith("import"):
for module in split(s.strip())[1:]:
if module in forbidden:
print "can't use %s module" % module
ok = 0
break
if ok:
exec(s)

while 1:
repl()

HTH.
Miki
 
T

Tommy Trojan

Mike,

thanks for the tip. I thought along the same lines, but that doesn't get
around the problem that the user could just embed an import in a script, or
import a script that I provide and that internally uses the module that
should not be exposed, i.e.:

in UserModule:

import RestrictedModule


This would get around the simple loop in checking the input arguments of the
interactive prompt. It needs to be a hook that is further down in the
system. The problem with an import hook is that it would need to distinguish
when it is okay to import the module (when I call it) and when it is not
okay (when my user calls it).

Thanks,
Thomas


Miki Tebeka said:
Hello Tommy,

Is there anything that can be done to import modules conditionally?
Any ideas?
Writing a custom REPL (read-eval-print-loop) should be easy enough:
import re
split = re.compile("\s+").split

forbidden = ("os", "sys")

def repl():
while 1:
s = raw_input(">>> ").strip()
ok = 1
if s.startswith("import"):
for module in split(s.strip())[1:]:
if module in forbidden:
print "can't use %s module" % module
ok = 0
break
if ok:
exec(s)

while 1:
repl()

HTH.
Miki
 
J

Josiah Carlson

import sys
import traceback


class MyDict(UserDict):
def __getitem__(self, key):
try:
raise ""
except:
a = traceback.extract_stack()
#do all your call checking on a
#similar checks for __setitem__

sys.modules = MyDict(sys.modules)

Do as many checks on the caller that tries to access a module via
sys.modules as you want.

You could also replace new.module with similar attribute get and set
permission checking, though my testing suggests that this may not be
enough (perhaps import keeps a reference to the original version of
new.module, or something).

- Josiah
 
T

Tommy Trojan

Josiah,

thanks, I will check out your solution. It looks similar to an import hook
to me. There is still a problem that the user could just reset sys.modules
to his own dict.

Thanks,
Thomas
 
J

Josiah Carlson

Tommy,

Heh, derive all of your classes from a single base class. Call this
base class "Restrictor" or something similarly funny. Give it the
equivalent __getattr__ and __setattr__ controls as the MyDict example's
__getitem__ and __setitem__.

Now all attribute accesses (including function calls) need to be
validated. It would slow things down considerably
(traceback.extract_stack() is slow), but you could restrict as much as
you want.

- Josiah
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,965
Members
47,512
Latest member
FinleyNick

Latest Threads

Top