PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/mapproxy/security/referrer.py

https://bitbucket.org/olt/mapproxy/
Python | 106 lines | 65 code | 17 blank | 24 comment | 17 complexity | 7a651cfeaf54d8c9701d8da66086b498 MD5 | raw file
Possible License(s): Apache-2.0
  1. # This file is part of the MapProxy project.
  2. # Copyright (C) 2010 Omniscale <http://omniscale.de>
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import re
  16. from urlparse import urlparse
  17. from mapproxy.response import Response
  18. class _None(object):
  19. """
  20. Accept empty referrers.
  21. """
  22. def __call__(self, referrer, _environ):
  23. return referrer is None
  24. NONE = _None()
  25. class _Blocked(object):
  26. """
  27. Accept referrers that were blocked by proxies (XXX, xxx or *****, etc.)
  28. """
  29. blocked = re.compile('^[xX*]+$')
  30. def __call__(self, referrer, _environ):
  31. if referrer is None:
  32. return False
  33. return self.blocked.match(referrer)
  34. BLOCKED = _Blocked()
  35. class _Self(object):
  36. """
  37. Accept referrers that are part of the request url.
  38. http://localhost/foo/ for http://localhost/foo/bar.png
  39. """
  40. def __call__(self, referrer, environ):
  41. if referrer is None:
  42. return False
  43. scheme, netloc, path, _params, _query, _fragment = urlparse(referrer)
  44. if scheme != environ['wsgi.url_scheme']: return False
  45. if netloc != environ['HTTP_HOST']:
  46. if _split_netloc(netloc, scheme) != _split_netloc(environ['HTTP_HOST'], scheme):
  47. return False
  48. return True
  49. SELF = _Self()
  50. def _split_netloc(netloc, scheme):
  51. if ':' in netloc:
  52. return tuple(netloc.split(':'))
  53. else:
  54. return netloc, {'http': '80', 'https': '443'}.get(scheme, None)
  55. class _Regex(object):
  56. def __init__(self, regex):
  57. self.regex_str = regex
  58. self.regex = re.compile(regex)
  59. def __call__(self, referrer, _environ):
  60. if referrer is None:
  61. return False
  62. return self.regex.match(referrer)
  63. def __repr__(self):
  64. return 'REGEX(%s)' % self.regex_str
  65. REGEX = _Regex
  66. class ReferrerFilter(object):
  67. def __init__(self, app, referrers=None):
  68. self.app = app
  69. if referrers is None:
  70. referrers = []
  71. self.referrers = referrers
  72. def check_referrer(self, environ):
  73. referrer = environ.get('HTTP_REFERER', None)
  74. for test in self.referrers:
  75. if isinstance(test, basestring):
  76. if referrer.startswith(test):
  77. return True
  78. elif callable(test):
  79. if test(referrer, environ):
  80. return True
  81. return False
  82. def restricted_response(self, environ, start_response):
  83. resp = Response('get out of here', status=404)
  84. return resp(environ, start_response)
  85. def __call__(self, environ, start_response):
  86. if not self.referrers or self.check_referrer(environ):
  87. return self.app(environ, start_response)
  88. else:
  89. return self.restricted_response(environ, start_response)