G
goodnamesalltaken
Hello fellow python users,
I've been working on a basic implementation of a privilege separated
web server, and I've goto the point of running a basic cgi script.
Basically when the execCGI function in my Unpriv.py program is called a
few things should happen, it should fork (which it does), the stdout of
the child should be redirected to a given pipe (which it does), and the
script should execute using execve(which is has problems with). Also
before the execCGI() fucntion is executed, a few important things
happen in __init__: os.chroot('/var/www/webroot/') the path is web
server root and os.setuid(33) where 33 is the uid of a user on my
machine. It seems me that the os.chroot() call is messing up the
os.execve() (which executes the cgi script). os.execve(pth, args,
envVariables) is only executed if os.path.exists(pth) returns True.
But when I run a CGI script that os.path.exists(pth) returns True for,
then os.execve(pth) python throws back the error:
File "/***/***/***/Unpriv.py", line 201, in execCGI
OSError: [Errno 2] No such file or directory
However I don't see how this is possible if os.path.exists(pth) returns
True, why is it os.execve() has problems finding it.
I thought it might be a user permission problem, but I've run it
without the chroot and with the setuid and it works fine. So I'm
pretty sure its something to do with the chroot conflicting with the
os.execve(). Also execution privileges for the script file are also
checked before execution.
Any insight would be greatly appreciated
Here are the relevant functions of Unpriv.py
class Unpriv(object):
def __init__(self):
pipes = sys.argv
self.fromParent, self.toParent = os.pipe()
# this is just how http requested are recieved from a privilege
part and sent back
os.dup2(int(pipes[2]), self. toParent) ##write
os.dup2(int(pipes[1]), self.fromParent) ##read
os.chroot('/var/www/webroot/') ##chrooting
os.setuid(33) ##setuid
def checkFileExists(self, pth): ## just calls os.path.exists()
return os.path.exists(pth)
def execCGI(self, pth):
##
x = pth.rfind('?')
if x > -1:
path = pth[:x]
query = pth[x+1:]
query = query.replace('+', ' ')
else:
path = pth
query = ''
##populate enviroment variables, not yet implemented
envVariables = {}
readEnd, writeEnd = os.pipe()
parentStout = sys.stdout.fileno()
args = ['']
args.append(query)
pid = os.fork()
if pid == 0:
##child
os.dup2(writeEnd, sys.stdout.fileno()) ##this works
## this is the problem!
if self.checkFileExists(pth):
os.execve(pth , args, envVariables)
else:
## just some debug info for me.
## in fact part of pth is there
##however for some reason execve doesn't see
print 'the directory listing is:',
os.listdir(os.getcwd())
os._exit(0)
else: #parent
#read the output from the script
scriptOutPut = os.read(readEnd, 100000)
#just some debug info for me
print 'OUTPUT FROM SCRIPT EXECUTION: ' , scriptOutPut
return scriptOutPut
Please excuse any problems with the formatting.
Thanks in advance.
I've been working on a basic implementation of a privilege separated
web server, and I've goto the point of running a basic cgi script.
Basically when the execCGI function in my Unpriv.py program is called a
few things should happen, it should fork (which it does), the stdout of
the child should be redirected to a given pipe (which it does), and the
script should execute using execve(which is has problems with). Also
before the execCGI() fucntion is executed, a few important things
happen in __init__: os.chroot('/var/www/webroot/') the path is web
server root and os.setuid(33) where 33 is the uid of a user on my
machine. It seems me that the os.chroot() call is messing up the
os.execve() (which executes the cgi script). os.execve(pth, args,
envVariables) is only executed if os.path.exists(pth) returns True.
But when I run a CGI script that os.path.exists(pth) returns True for,
then os.execve(pth) python throws back the error:
File "/***/***/***/Unpriv.py", line 201, in execCGI
OSError: [Errno 2] No such file or directory
However I don't see how this is possible if os.path.exists(pth) returns
True, why is it os.execve() has problems finding it.
I thought it might be a user permission problem, but I've run it
without the chroot and with the setuid and it works fine. So I'm
pretty sure its something to do with the chroot conflicting with the
os.execve(). Also execution privileges for the script file are also
checked before execution.
Any insight would be greatly appreciated
Here are the relevant functions of Unpriv.py
class Unpriv(object):
def __init__(self):
pipes = sys.argv
self.fromParent, self.toParent = os.pipe()
# this is just how http requested are recieved from a privilege
part and sent back
os.dup2(int(pipes[2]), self. toParent) ##write
os.dup2(int(pipes[1]), self.fromParent) ##read
os.chroot('/var/www/webroot/') ##chrooting
os.setuid(33) ##setuid
def checkFileExists(self, pth): ## just calls os.path.exists()
return os.path.exists(pth)
def execCGI(self, pth):
##
x = pth.rfind('?')
if x > -1:
path = pth[:x]
query = pth[x+1:]
query = query.replace('+', ' ')
else:
path = pth
query = ''
##populate enviroment variables, not yet implemented
envVariables = {}
readEnd, writeEnd = os.pipe()
parentStout = sys.stdout.fileno()
args = ['']
args.append(query)
pid = os.fork()
if pid == 0:
##child
os.dup2(writeEnd, sys.stdout.fileno()) ##this works
## this is the problem!
if self.checkFileExists(pth):
os.execve(pth , args, envVariables)
else:
## just some debug info for me.
## in fact part of pth is there
##however for some reason execve doesn't see
print 'the directory listing is:',
os.listdir(os.getcwd())
os._exit(0)
else: #parent
#read the output from the script
scriptOutPut = os.read(readEnd, 100000)
#just some debug info for me
print 'OUTPUT FROM SCRIPT EXECUTION: ' , scriptOutPut
return scriptOutPut
Please excuse any problems with the formatting.
Thanks in advance.