from_file.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # This file is part of Radicale Server - Calendar Server
  2. # Copyright © 2012-2017 Guillaume Ayoub
  3. # Copyright © 2017-2019 Unrud <unrud@outlook.com>
  4. #
  5. # This library is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This library is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with Radicale. If not, see <http://www.gnu.org/licenses/>.
  17. import configparser
  18. import re
  19. from radicale import pathutils, rights
  20. from radicale.log import logger
  21. class Rights(rights.BaseRights):
  22. def __init__(self, configuration):
  23. super().__init__(configuration)
  24. self.filename = configuration.get("rights", "file")
  25. def authorized(self, user, path, permissions):
  26. user = user or ""
  27. sane_path = pathutils.strip_path(path)
  28. # Prevent "regex injection"
  29. user_escaped = re.escape(user)
  30. sane_path_escaped = re.escape(sane_path)
  31. rights_config = configparser.ConfigParser(
  32. {"login": user_escaped, "path": sane_path_escaped})
  33. try:
  34. if not rights_config.read(self.filename):
  35. raise RuntimeError("No such file: %r" %
  36. self.filename)
  37. except Exception as e:
  38. raise RuntimeError("Failed to load rights file %r: %s" %
  39. (self.filename, e)) from e
  40. for section in rights_config.sections():
  41. try:
  42. user_pattern = rights_config.get(section, "user")
  43. collection_pattern = rights_config.get(section, "collection")
  44. user_match = re.fullmatch(user_pattern, user)
  45. collection_match = user_match and re.fullmatch(
  46. collection_pattern.format(
  47. *map(re.escape, user_match.groups())), sane_path)
  48. except Exception as e:
  49. raise RuntimeError("Error in section %r of rights file %r: "
  50. "%s" % (section, self.filename, e)) from e
  51. if user_match and collection_match:
  52. logger.debug("Rule %r:%r matches %r:%r from section %r",
  53. user, sane_path, user_pattern,
  54. collection_pattern, section)
  55. return rights.intersect_permissions(
  56. permissions, rights_config.get(section, "permissions"))
  57. else:
  58. logger.debug("Rule %r:%r doesn't match %r:%r from section %r",
  59. user, sane_path, user_pattern,
  60. collection_pattern, section)
  61. logger.info("Rights: %r:%r doesn't match any section", user, sane_path)
  62. return ""