PAM.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # This file is part of Radicale Server - Calendar Server
  2. # Copyright © 2011 Henry-Nicolas Tourneur
  3. # Copyright © 2016 Guillaume Ayoub
  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. """
  18. PAM authentication.
  19. Authentication based on the ``pam-python`` module.
  20. """
  21. import grp
  22. import pwd
  23. import pam
  24. from .. import config, log
  25. GROUP_MEMBERSHIP = config.get("auth", "pam_group_membership")
  26. # Compatibility for old versions of python-pam.
  27. if hasattr(pam, "pam"):
  28. def pam_authenticate(*args, **kwargs):
  29. return pam.pam().authenticate(*args, **kwargs)
  30. else:
  31. def pam_authenticate(*args, **kwargs):
  32. return pam.authenticate(*args, **kwargs)
  33. def is_authenticated(user, password):
  34. """Check if ``user``/``password`` couple is valid."""
  35. if user is None or password is None:
  36. return False
  37. # Check whether the user exists in the PAM system
  38. try:
  39. pwd.getpwnam(user).pw_uid
  40. except KeyError:
  41. log.LOGGER.debug("User %s not found" % user)
  42. return False
  43. else:
  44. log.LOGGER.debug("User %s found" % user)
  45. # Check whether the group exists
  46. try:
  47. # Obtain supplementary groups
  48. members = grp.getgrnam(GROUP_MEMBERSHIP).gr_mem
  49. except KeyError:
  50. log.LOGGER.debug(
  51. "The PAM membership required group (%s) doesn't exist" %
  52. GROUP_MEMBERSHIP)
  53. return False
  54. # Check whether the user exists
  55. try:
  56. # Get user primary group
  57. primary_group = grp.getgrgid(pwd.getpwnam(user).pw_gid).gr_name
  58. except KeyError:
  59. log.LOGGER.debug("The PAM user (%s) doesn't exist" % user)
  60. return False
  61. # Check whether the user belongs to the required group
  62. # (primary or supplementary)
  63. if primary_group == GROUP_MEMBERSHIP or user in members:
  64. log.LOGGER.debug(
  65. "The PAM user belongs to the required group (%s)" %
  66. GROUP_MEMBERSHIP)
  67. # Check the password
  68. if pam_authenticate(user, password, service='radicale'):
  69. return True
  70. else:
  71. log.LOGGER.debug("Wrong PAM password")
  72. else:
  73. log.LOGGER.debug(
  74. "The PAM user doesn't belong to the required group (%s)" %
  75. GROUP_MEMBERSHIP)
  76. return False