from_file.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. # This file is part of Radicale Server - Calendar Server
  2. # Copyright © 2012-2017 Guillaume Ayoub
  3. # Copyright © 2017-2018 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 os.path
  19. import re
  20. from radicale import pathutils, rights
  21. from radicale.log import logger
  22. class Rights(rights.BaseRights):
  23. def __init__(self, configuration):
  24. super().__init__(configuration)
  25. self.filename = os.path.expanduser(configuration.get("rights", "file"))
  26. def authorized(self, user, path, permissions):
  27. user = user or ""
  28. sane_path = pathutils.strip_path(path)
  29. # Prevent "regex injection"
  30. user_escaped = re.escape(user)
  31. sane_path_escaped = re.escape(sane_path)
  32. rights_config = configparser.ConfigParser(
  33. {"login": user_escaped, "path": sane_path_escaped})
  34. try:
  35. if not rights_config.read(self.filename):
  36. raise RuntimeError("No such file: %r" %
  37. self.filename)
  38. except Exception as e:
  39. raise RuntimeError("Failed to load rights file %r: %s" %
  40. (self.filename, e)) from e
  41. for section in rights_config.sections():
  42. try:
  43. user_pattern = rights_config.get(section, "user")
  44. collection_pattern = rights_config.get(section, "collection")
  45. user_match = re.fullmatch(user_pattern, user)
  46. collection_match = user_match and re.fullmatch(
  47. collection_pattern.format(
  48. *map(re.escape, user_match.groups())), sane_path)
  49. except Exception as e:
  50. raise RuntimeError("Error in section %r of rights file %r: "
  51. "%s" % (section, self.filename, e)) from e
  52. if user_match and collection_match:
  53. logger.debug("Rule %r:%r matches %r:%r from section %r",
  54. user, sane_path, user_pattern,
  55. collection_pattern, section)
  56. return rights.intersect_permissions(
  57. permissions, rights_config.get(section, "permissions"))
  58. else:
  59. logger.debug("Rule %r:%r doesn't match %r:%r from section %r",
  60. user, sane_path, user_pattern,
  61. collection_pattern, section)
  62. logger.info("Rights: %r:%r doesn't match any section", user, sane_path)
  63. return ""