mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-20 05:28:04 +00:00
webish: localfile=/localdir= are now disabled by default, a special switch is required to enable them
This commit is contained in:
parent
b4a0effe30
commit
2f5a27316f
@ -26,6 +26,7 @@ class Client(node.Node, Referenceable):
|
||||
STOREDIR = 'storage'
|
||||
NODETYPE = "client"
|
||||
WEBPORTFILE = "webport"
|
||||
WEB_ALLOW_LOCAL_ACCESS_FILE = "webport_allow_localfile"
|
||||
INTRODUCER_FURL_FILE = "introducer.furl"
|
||||
MY_FURL_FILE = "myself.furl"
|
||||
SUICIDE_PREVENTION_HOTLINE_FILE = "suicide_prevention_hotline"
|
||||
@ -49,7 +50,12 @@ class Client(node.Node, Referenceable):
|
||||
f = open(WEBPORTFILE, "r")
|
||||
webport = f.read().strip() # strports string
|
||||
f.close()
|
||||
self.add_service(WebishServer(webport))
|
||||
ws = WebishServer(webport)
|
||||
local_access_file = os.path.join(self.basedir,
|
||||
self.WEB_ALLOW_LOCAL_ACCESS_FILE)
|
||||
if os.path.exists(local_access_file):
|
||||
ws.allow_local_access(True)
|
||||
self.add_service(ws)
|
||||
|
||||
INTRODUCER_FURL_FILE = os.path.join(self.basedir,
|
||||
self.INTRODUCER_FURL_FILE)
|
||||
|
@ -158,7 +158,8 @@ class WebMixin(object):
|
||||
def setUp(self):
|
||||
self.s = MyClient()
|
||||
self.s.startService()
|
||||
s = webish.WebishServer("0")
|
||||
self.ws = s = webish.WebishServer("0")
|
||||
s.allow_local_access(True)
|
||||
s.setServiceParent(self.s)
|
||||
port = s.listener._port.getHost().port
|
||||
self.webish_url = "http://localhost:%d" % port
|
||||
@ -461,11 +462,15 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addBoth(self.should404, "test_GET_FILEURL_json_missing")
|
||||
return d
|
||||
|
||||
def disable_local_access(self, res=None):
|
||||
self.ws.allow_local_access(False)
|
||||
return res
|
||||
|
||||
def test_GET_FILEURL_localfile(self):
|
||||
localfile = os.path.abspath("web/GET_FILEURL_localfile")
|
||||
url = "/vdrive/global/foo/bar.txt?t=download&localfile=%s" % localfile
|
||||
fileutil.make_dirs("web")
|
||||
d = self.GET("/vdrive/global/foo/bar.txt?t=download&localfile=%s"
|
||||
% localfile)
|
||||
d = self.GET(url)
|
||||
def _done(res):
|
||||
self.failUnless(os.path.exists(localfile))
|
||||
data = open(localfile, "rb").read()
|
||||
@ -473,6 +478,17 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addCallback(_done)
|
||||
return d
|
||||
|
||||
def test_GET_FILEURL_localfile_disabled(self):
|
||||
localfile = os.path.abspath("web/GET_FILEURL_localfile_disabled")
|
||||
url = "/vdrive/global/foo/bar.txt?t=download&localfile=%s" % localfile
|
||||
fileutil.make_dirs("web")
|
||||
self.disable_local_access()
|
||||
d = self.GET(url)
|
||||
d.addBoth(self.shouldFail, error.Error, "localfile disabled",
|
||||
"403 Forbidden",
|
||||
"local file access is disabled")
|
||||
return d
|
||||
|
||||
def test_GET_FILEURL_localfile_nonlocal(self):
|
||||
# TODO: somehow pretend that we aren't local, and verify that the
|
||||
# server refuses to write to local files, probably by changing the
|
||||
@ -510,12 +526,12 @@ class Web(WebMixin, unittest.TestCase):
|
||||
|
||||
def test_PUT_NEWFILEURL_localfile(self):
|
||||
localfile = os.path.abspath("web/PUT_NEWFILEURL_localfile")
|
||||
url = "/vdrive/global/foo/new.txt?t=upload&localfile=%s" % localfile
|
||||
fileutil.make_dirs("web")
|
||||
f = open(localfile, "wb")
|
||||
f.write(self.NEWFILE_CONTENTS)
|
||||
f.close()
|
||||
d = self.PUT("/vdrive/global/foo/new.txt?t=upload&localfile=%s" %
|
||||
localfile, "")
|
||||
d = self.PUT(url, "")
|
||||
def _check(res):
|
||||
self.failUnless("new.txt" in self._foo_node.children)
|
||||
new_uri = self._foo_node.children["new.txt"]
|
||||
@ -525,6 +541,20 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
|
||||
def test_PUT_NEWFILEURL_localfile_disabled(self):
|
||||
localfile = os.path.abspath("web/PUT_NEWFILEURL_localfile_disabled")
|
||||
url = "/vdrive/global/foo/new.txt?t=upload&localfile=%s" % localfile
|
||||
fileutil.make_dirs("web")
|
||||
f = open(localfile, "wb")
|
||||
f.write(self.NEWFILE_CONTENTS)
|
||||
f.close()
|
||||
self.disable_local_access()
|
||||
d = self.PUT(url, "")
|
||||
d.addBoth(self.shouldFail, error.Error, "put localfile disabled",
|
||||
"403 Forbidden",
|
||||
"local file access is disabled")
|
||||
return d
|
||||
|
||||
def test_PUT_NEWFILEURL_localfile_mkdirs(self):
|
||||
localfile = os.path.abspath("web/PUT_NEWFILEURL_localfile_mkdirs")
|
||||
fileutil.make_dirs("web")
|
||||
@ -715,6 +745,16 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
|
||||
def test_GET_DIRURL_localdir_disabled(self):
|
||||
localdir = os.path.abspath("web/GET_DIRURL_localdir_disabled")
|
||||
fileutil.make_dirs("web")
|
||||
self.disable_local_access()
|
||||
d = self.GET("/vdrive/global/foo?t=download&localdir=%s" % localdir)
|
||||
d.addBoth(self.shouldFail, error.Error, "localfile disabled",
|
||||
"403 Forbidden",
|
||||
"local file access is disabled")
|
||||
return d
|
||||
|
||||
def test_GET_DIRURL_localdir_nonabsolute(self):
|
||||
localdir = "web/nonabsolute/dirpath"
|
||||
fileutil.make_dirs("web/nonabsolute")
|
||||
@ -778,6 +818,25 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
|
||||
def test_PUT_NEWDIRURL_localdir_disabled(self):
|
||||
localdir = os.path.abspath("web/PUT_NEWDIRURL_localdir_disabled")
|
||||
# create some files there
|
||||
fileutil.make_dirs(os.path.join(localdir, "one"))
|
||||
fileutil.make_dirs(os.path.join(localdir, "one/sub"))
|
||||
fileutil.make_dirs(os.path.join(localdir, "two"))
|
||||
fileutil.make_dirs(os.path.join(localdir, "three"))
|
||||
self.touch(localdir, "three/foo.txt")
|
||||
self.touch(localdir, "three/bar.txt")
|
||||
self.touch(localdir, "zap.zip")
|
||||
|
||||
self.disable_local_access()
|
||||
d = self.PUT("/vdrive/global/newdir?t=upload&localdir=%s"
|
||||
% localdir, "")
|
||||
d.addBoth(self.shouldFail, error.Error, "localfile disabled",
|
||||
"403 Forbidden",
|
||||
"local file access is disabled")
|
||||
return d
|
||||
|
||||
def test_PUT_NEWDIRURL_localdir_mkdirs(self):
|
||||
localdir = os.path.abspath("web/PUT_NEWDIRURL_localdir_mkdirs")
|
||||
# create some files there
|
||||
|
@ -19,6 +19,9 @@ def getxmlfile(name):
|
||||
|
||||
class IClient(Interface):
|
||||
pass
|
||||
class ILocalAccess(Interface):
|
||||
def allow_local_access():
|
||||
pass
|
||||
|
||||
|
||||
# we must override twisted.web.http.Request.requestReceived with a version
|
||||
@ -347,7 +350,15 @@ class NeedAbsolutePathError:
|
||||
req.setHeader("content-type", "text/plain")
|
||||
return "localfile= or localdir= requires an absolute path"
|
||||
|
||||
|
||||
class LocalAccessDisabledError:
|
||||
implements(inevow.IResource)
|
||||
|
||||
def renderHTTP(self, ctx):
|
||||
req = inevow.IRequest(ctx)
|
||||
req.setResponseCode(http.FORBIDDEN)
|
||||
req.setHeader("content-type", "text/plain")
|
||||
return "local file access is disabled"
|
||||
|
||||
|
||||
class LocalFileDownloader(resource.Resource):
|
||||
def __init__(self, filenode, local_filename):
|
||||
@ -832,6 +843,8 @@ class VDrive(rend.Page):
|
||||
if localdir != os.path.abspath(localdir):
|
||||
return NeedAbsolutePathError(), ()
|
||||
if localfile or localdir:
|
||||
if not ILocalAccess(ctx).allow_local_access():
|
||||
return LocalAccessDisabledError(), ()
|
||||
if req.getHost().host != LOCALHOST:
|
||||
return NeedLocalhostError(), ()
|
||||
# TODO: think about clobbering/revealing config files and node secrets
|
||||
@ -1032,18 +1045,30 @@ class Root(rend.Page):
|
||||
return T.div[form]
|
||||
|
||||
|
||||
class LocalAccess:
|
||||
implements(ILocalAccess)
|
||||
def __init__(self):
|
||||
self.local_access = False
|
||||
def allow_local_access(self):
|
||||
return self.local_access
|
||||
|
||||
class WebishServer(service.MultiService):
|
||||
name = "webish"
|
||||
|
||||
def __init__(self, webport):
|
||||
def __init__(self, webport, local_access=False):
|
||||
service.MultiService.__init__(self)
|
||||
self.root = Root()
|
||||
self.site = site = appserver.NevowSite(self.root)
|
||||
self.site.requestFactory = MyRequest
|
||||
self.allow_local = LocalAccess()
|
||||
self.site.remember(self.allow_local, ILocalAccess)
|
||||
s = strports.service(webport, site)
|
||||
s.setServiceParent(self)
|
||||
self.listener = s # stash it so the tests can query for the portnum
|
||||
|
||||
def allow_local_access(self, enable=True):
|
||||
self.allow_local.local_access = enable
|
||||
|
||||
def startService(self):
|
||||
service.MultiService.startService(self)
|
||||
# to make various services available to render_* methods, we stash a
|
||||
|
Loading…
Reference in New Issue
Block a user