Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sasl.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """
  2. sasl.py - support for SASL mechanism
  3. See https://www.python-ldap.org/ for details.
  4. Description:
  5. The ldap.sasl module provides SASL authentication classes.
  6. Each class provides support for one SASL mechanism. This is done by
  7. implementing a callback() - method, which will be called by the
  8. LDAPObject's sasl_bind_s() method
  9. Implementing support for new sasl mechanism is very easy --- see
  10. the examples of digest_md5 and gssapi.
  11. """
  12. from ldap import __version__
  13. if __debug__:
  14. # Tracing is only supported in debugging mode
  15. from ldap import _trace_level, _trace_file
  16. # These are the SASL callback id's , as defined in sasl.h
  17. CB_USER = 0x4001
  18. CB_AUTHNAME = 0x4002
  19. CB_LANGUAGE = 0x4003
  20. CB_PASS = 0x4004
  21. CB_ECHOPROMPT = 0x4005
  22. CB_NOECHOPROMPT = 0x4006
  23. CB_GETREALM = 0x4008
  24. class sasl:
  25. """
  26. This class handles SASL interactions for authentication.
  27. If an instance of this class is passed to ldap's sasl_bind_s()
  28. method, the library will call its callback() method. For
  29. specific SASL authentication mechanisms, this method can be
  30. overridden
  31. """
  32. def __init__(self, cb_value_dict, mech):
  33. """
  34. The (generic) base class takes a cb_value_dictionary of
  35. question-answer pairs. Questions are specified by the respective
  36. SASL callback id's. The mech argument is a string that specifies
  37. the SASL mechaninsm to be uesd.
  38. """
  39. self.cb_value_dict = cb_value_dict or {}
  40. if not isinstance(mech, bytes):
  41. mech = mech.encode('utf-8')
  42. self.mech = mech
  43. def callback(self, cb_id, challenge, prompt, defresult):
  44. """
  45. The callback method will be called by the sasl_bind_s()
  46. method several times. Each time it will provide the id, which
  47. tells us what kind of information is requested (the CB_*
  48. constants above). The challenge might be a short (English) text
  49. or some binary string, from which the return value is calculated.
  50. The prompt argument is always a human-readable description string;
  51. The defresult is a default value provided by the sasl library
  52. Currently, we do not use the challenge and prompt information, and
  53. return only information which is stored in the self.cb_value_dict
  54. cb_value_dictionary. Note that the current callback interface is not very
  55. useful for writing generic sasl GUIs, which would need to know all
  56. the questions to ask, before the answers are returned to the sasl
  57. lib (in contrast to one question at a time).
  58. Unicode strings are always converted to bytes.
  59. """
  60. # The following print command might be useful for debugging
  61. # new sasl mechanisms. So it is left here
  62. cb_result = self.cb_value_dict.get(cb_id, defresult) or ''
  63. if __debug__:
  64. if _trace_level >= 1:
  65. _trace_file.write("*** id=%d, challenge=%s, prompt=%s, defresult=%s\n-> %s\n" % (
  66. cb_id,
  67. challenge,
  68. prompt,
  69. repr(defresult),
  70. repr(self.cb_value_dict.get(cb_result))
  71. ))
  72. if not isinstance(cb_result, bytes):
  73. cb_result = cb_result.encode('utf-8')
  74. return cb_result
  75. class cram_md5(sasl):
  76. """
  77. This class handles SASL CRAM-MD5 authentication.
  78. """
  79. def __init__(self, authc_id, password, authz_id=""):
  80. auth_dict = {
  81. CB_AUTHNAME: authc_id,
  82. CB_PASS: password,
  83. CB_USER: authz_id,
  84. }
  85. sasl.__init__(self, auth_dict, "CRAM-MD5")
  86. class digest_md5(sasl):
  87. """
  88. This class handles SASL DIGEST-MD5 authentication.
  89. """
  90. def __init__(self, authc_id, password, authz_id=""):
  91. auth_dict = {
  92. CB_AUTHNAME: authc_id,
  93. CB_PASS: password,
  94. CB_USER: authz_id,
  95. }
  96. sasl.__init__(self, auth_dict, "DIGEST-MD5")
  97. class gssapi(sasl):
  98. """
  99. This class handles SASL GSSAPI (i.e. Kerberos V) authentication.
  100. """
  101. def __init__(self, authz_id=""):
  102. sasl.__init__(self, {CB_USER: authz_id}, "GSSAPI")
  103. class external(sasl):
  104. """
  105. This class handles SASL EXTERNAL authentication
  106. (i.e. X.509 client certificate)
  107. """
  108. def __init__(self, authz_id=""):
  109. sasl.__init__(self, {CB_USER: authz_id}, "EXTERNAL")