diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | libpathod/app.py | 6 | ||||
| -rw-r--r-- | libpathod/language.py | 21 | ||||
| -rw-r--r-- | libpathod/pathod.py | 13 | ||||
| -rw-r--r-- | test/test_app.py | 8 | ||||
| -rw-r--r-- | test/test_language.py | 2 | ||||
| -rw-r--r-- | test/test_pathod.py | 2 | 
7 files changed, 33 insertions, 21 deletions
@@ -7,5 +7,7 @@ MANIFEST  *.swp  /doc  .coverage +.noseids  netlib  venv + diff --git a/libpathod/app.py b/libpathod/app.py index 6f12c0a2..38d0be33 100644 --- a/libpathod/app.py +++ b/libpathod/app.py @@ -123,18 +123,14 @@ def _preview(is_request):          args["syntaxerror"] = str(v)          args["marked"] = v.marked()          return render(template, False, **args) -    except language.FileAccessDenied: -        args["error"] = "File access is disabled." -        return render(template, False, **args)      s = cStringIO.StringIO()      args["pauses"] = r.preview_safe() -    c = app.config["pathod"].check_policy(r) +    c = app.config["pathod"].check_policy(r, app.config["pathod"].request_settings)      if c:          args["error"] = c          return render(template, False, **args) -      if is_request:          r.serve(s, app.config["pathod"].request_settings, host="example.com")      else: diff --git a/libpathod/language.py b/libpathod/language.py index 31239b74..5d6471e6 100644 --- a/libpathod/language.py +++ b/libpathod/language.py @@ -345,7 +345,7 @@ class Body:          self.value = value      def accept(self, settings, r): -        r.body = self.value.get_generator(settings) +        r.body = self      @classmethod      def expr(klass): @@ -353,6 +353,11 @@ class Body:          e = e + Value          return e.setParseAction(lambda x: klass(*x)) +    def values(self, settings): +        return [ +                self.value.get_generator(settings), +            ] +  class Raw:      def accept(self, settings, r): @@ -532,7 +537,7 @@ class Code:  class Message:      version = "HTTP/1.1"      def __init__(self): -        self.body = LiteralGenerator("") +        self.body = None          self.headers = []          self.actions = []          self.raw = False @@ -546,7 +551,8 @@ class Message:          for h in self.headervals(settings, request_host):              l += len(h)          l += 2 -        l += len(self.body) +        if self.body: +            l += len(self.body.value.get_generator(settings))          return l      def preview_safe(self): @@ -574,7 +580,7 @@ class Message:                  hdrs.append(                      Header(                          ValueLiteral("Content-Length"), -                        ValueLiteral(str(len(self.body))), +                        ValueLiteral(str(len(self.body.value.get_generator(settings)))),                      )                  )              if request_host: @@ -624,7 +630,7 @@ class Message:          vals.extend(hdrs)          vals.append("\r\n")          if self.body: -            vals.append(self.body) +            vals.append(self.body.value.get_generator(settings))          vals.reverse()          actions = self.ready_actions(settings, request_host) @@ -638,6 +644,9 @@ class Message:          for i in self.logattrs:              v = getattr(self, i)              # Careful not to log any VALUE specs without sanitizing them first. We truncate at 1k. +            if hasattr(v, "values"): +                v = [x[:TRUNCATE] for x in v.values(settings)] +                v = "".join(v)              if hasattr(v, "__len__"):                  v = v[:TRUNCATE]                  v = v.encode("string_escape") @@ -757,7 +766,7 @@ class PathodErrorResponse(Response):          Response.__init__(self)          self.code = 800          self.msg = LiteralGenerator(msg) -        self.body = LiteralGenerator("pathod error: " + (body or msg)) +        self.body = Body(ValueLiteral("pathod error: " + (body or msg)))          self.headers = [              Header(ValueLiteral("Content-Type"), ValueLiteral("text/plain")),          ] diff --git a/libpathod/pathod.py b/libpathod/pathod.py index d80a9018..131dbc3c 100644 --- a/libpathod/pathod.py +++ b/libpathod/pathod.py @@ -18,7 +18,7 @@ class PathodHandler(tcp.BaseHandler):          self.sni = connection.get_servername()      def serve_crafted(self, crafted, request_log): -        c = self.server.check_policy(crafted) +        c = self.server.check_policy(crafted, self.server.request_settings)          if c:              err = language.PathodErrorResponse(c)              err.serve(self.wfile, self.server.request_settings) @@ -100,9 +100,6 @@ class PathodHandler(tcp.BaseHandler):                          "Parse Error",                          "Error parsing response spec: %s\n"%v.msg + v.marked()                      ) -            except language.FileAccessDenied: -                self.info("File access denied") -                crafted = language.PathodErrorResponse("Access Denied")              return self.serve_crafted(crafted, request_log)          elif self.server.noweb:              crafted = language.PathodErrorResponse("Access Denied") @@ -215,11 +212,15 @@ class Pathod(tcp.TCPServer):                      raise PathodError("Invalid page spec in anchor: '%s', %s"%(i[1], str(v)))                  self.anchors.append((arex, i[1])) -    def check_policy(self, req): +    def check_policy(self, req, settings):          """              A policy check that verifies the request size is withing limits.          """ -        if self.sizelimit and req.maximum_length({}, None) > self.sizelimit: +        try: +            l = req.maximum_length(settings, None) +        except language.FileAccessDenied, v: +            return "File access denied." +        if self.sizelimit and l > self.sizelimit:              return "Response too large."          if self.nohang and any([isinstance(i, language.PauseAt) for i in req.actions]):              return "Pauses have been disabled." diff --git a/test/test_app.py b/test/test_app.py index 7b2451d6..b3194052 100644 --- a/test/test_app.py +++ b/test/test_app.py @@ -47,9 +47,13 @@ class TestApp(tutils.DaemonTests):          assert r.status_code == 200          assert 'Response' in r.content -        r = self.getpath("/response_preview", params=dict(spec="200:b<foo")) +        r = self.getpath("/response_preview", params=dict(spec="200:b<nonexistent"))          assert r.status_code == 200 -        assert 'File access is disabled' in r.content +        assert 'File access denied' in r.content + +        r = self.getpath("/response_preview", params=dict(spec="200:b<file")) +        assert r.status_code == 200 +        assert 'testfile' in r.content      def test_request_preview(self):          r = self.getpath("/request_preview", params=dict(spec="get:/")) diff --git a/test/test_language.py b/test/test_language.py index e5ec51d2..54f96d51 100644 --- a/test/test_language.py +++ b/test/test_language.py @@ -508,7 +508,7 @@ class TestResponse:          r = language.parse_response({}, "400'msg':b@100b")          assert r.msg == "msg" -        assert r.body[:] +        assert r.body.values({})          assert str(r)      def test_render(self): diff --git a/test/test_pathod.py b/test/test_pathod.py index 195c7333..83f57727 100644 --- a/test/test_pathod.py +++ b/test/test_pathod.py @@ -141,7 +141,7 @@ class CommonTests(tutils.DaemonTests):      def test_source_access_denied(self):          rsp = self.get("200:b</foo")          assert rsp.status_code == 800 -        assert "Access Denied" in rsp.content +        assert "File access denied" in rsp.content  class TestDaemon(CommonTests):  | 
