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.

bind.py 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. """
  2. """
  3. # Created on 2013.05.31
  4. #
  5. # Author: Giovanni Cannata
  6. #
  7. # Copyright 2013 - 2018 Giovanni Cannata
  8. #
  9. # This file is part of ldap3.
  10. #
  11. # ldap3 is free software: you can redistribute it and/or modify
  12. # it under the terms of the GNU Lesser General Public License as published
  13. # by the Free Software Foundation, either version 3 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # ldap3 is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU Lesser General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU Lesser General Public License
  22. # along with ldap3 in the COPYING and COPYING.LESSER files.
  23. # If not, see <http://www.gnu.org/licenses/>.
  24. from .. import SIMPLE, ANONYMOUS, SASL, STRING_TYPES
  25. from ..core.results import RESULT_CODES
  26. from ..core.exceptions import LDAPUserNameIsMandatoryError, LDAPPasswordIsMandatoryError, LDAPUnknownAuthenticationMethodError, LDAPUserNameNotAllowedError
  27. from ..protocol.sasl.sasl import validate_simple_password
  28. from ..protocol.rfc4511 import Version, AuthenticationChoice, Simple, BindRequest, ResultCode, SaslCredentials, BindResponse, \
  29. LDAPDN, LDAPString, Referral, ServerSaslCreds, SicilyPackageDiscovery, SicilyNegotiate, SicilyResponse
  30. from ..protocol.convert import authentication_choice_to_dict, referrals_to_list
  31. from ..utils.conv import to_unicode, to_raw
  32. # noinspection PyUnresolvedReferences
  33. def bind_operation(version,
  34. authentication,
  35. name='',
  36. password=None,
  37. sasl_mechanism=None,
  38. sasl_credentials=None,
  39. auto_encode=False):
  40. # BindRequest ::= [APPLICATION 0] SEQUENCE {
  41. # version INTEGER (1 .. 127),
  42. # name LDAPDN,
  43. # authentication AuthenticationChoice }
  44. request = BindRequest()
  45. request['version'] = Version(version)
  46. if name is None:
  47. name = ''
  48. if isinstance(name, STRING_TYPES):
  49. request['name'] = to_unicode(name) if auto_encode else name
  50. if authentication == SIMPLE:
  51. if not name:
  52. raise LDAPUserNameIsMandatoryError('user name is mandatory in simple bind')
  53. if password:
  54. request['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(validate_simple_password(password)))
  55. else:
  56. raise LDAPPasswordIsMandatoryError('password is mandatory in simple bind')
  57. elif authentication == SASL:
  58. sasl_creds = SaslCredentials()
  59. sasl_creds['mechanism'] = sasl_mechanism
  60. if sasl_credentials is not None:
  61. sasl_creds['credentials'] = sasl_credentials
  62. # else:
  63. # sasl_creds['credentials'] = None
  64. request['authentication'] = AuthenticationChoice().setComponentByName('sasl', sasl_creds)
  65. elif authentication == ANONYMOUS:
  66. if name:
  67. raise LDAPUserNameNotAllowedError('user name not allowed in anonymous bind')
  68. request['name'] = ''
  69. request['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(''))
  70. elif authentication == 'SICILY_PACKAGE_DISCOVERY': # https://msdn.microsoft.com/en-us/library/cc223501.aspx
  71. request['name'] = ''
  72. request['authentication'] = AuthenticationChoice().setComponentByName('sicilyPackageDiscovery', SicilyPackageDiscovery(''))
  73. elif authentication == 'SICILY_NEGOTIATE_NTLM': # https://msdn.microsoft.com/en-us/library/cc223501.aspx
  74. request['name'] = 'NTLM'
  75. request['authentication'] = AuthenticationChoice().setComponentByName('sicilyNegotiate', SicilyNegotiate(name.create_negotiate_message())) # ntlm client in self.name
  76. elif authentication == 'SICILY_RESPONSE_NTLM': # https://msdn.microsoft.com/en-us/library/cc223501.aspx
  77. name.parse_challenge_message(password) # server_creds returned by server in password
  78. server_creds = name.create_authenticate_message()
  79. if server_creds:
  80. request['name'] = ''
  81. request['authentication'] = AuthenticationChoice().setComponentByName('sicilyResponse', SicilyResponse(server_creds))
  82. else:
  83. request = None
  84. else:
  85. raise LDAPUnknownAuthenticationMethodError('unknown authentication method')
  86. return request
  87. def bind_request_to_dict(request):
  88. return {'version': int(request['version']),
  89. 'name': str(request['name']),
  90. 'authentication': authentication_choice_to_dict(request['authentication'])}
  91. def bind_response_operation(result_code,
  92. matched_dn='',
  93. diagnostic_message='',
  94. referral=None,
  95. server_sasl_credentials=None):
  96. # BindResponse ::= [APPLICATION 1] SEQUENCE {
  97. # COMPONENTS OF LDAPResult,
  98. # serverSaslCreds [7] OCTET STRING OPTIONAL }
  99. response = BindResponse()
  100. response['resultCode'] = ResultCode(result_code)
  101. response['matchedDN'] = LDAPDN(matched_dn)
  102. response['diagnosticMessage'] = LDAPString(diagnostic_message)
  103. if referral:
  104. response['referral'] = Referral(referral)
  105. if server_sasl_credentials:
  106. response['serverSaslCreds'] = ServerSaslCreds(server_sasl_credentials)
  107. return response
  108. def bind_response_to_dict(response):
  109. return {'result': int(response['resultCode']),
  110. 'description': ResultCode().getNamedValues().getName(response['resultCode']),
  111. 'dn': str(response['matchedDN']),
  112. 'message': str(response['diagnosticMessage']),
  113. 'referrals': referrals_to_list(response['referral']),
  114. 'saslCreds': bytes(response['serverSaslCreds']) if response['serverSaslCreds'] is not None and response['serverSaslCreds'].hasValue() else None}
  115. def sicily_bind_response_to_dict(response):
  116. return {'result': int(response['resultCode']),
  117. 'description': ResultCode().getNamedValues().getName(response['resultCode']),
  118. 'server_creds': bytes(response['matchedDN']),
  119. 'error_message': str(response['diagnosticMessage'])}
  120. def bind_response_to_dict_fast(response):
  121. response_dict = dict()
  122. response_dict['result'] = int(response[0][3]) # resultCode
  123. response_dict['description'] = RESULT_CODES[response_dict['result']]
  124. response_dict['dn'] = to_unicode(response[1][3], from_server=True) # matchedDN
  125. response_dict['message'] = to_unicode(response[2][3], from_server=True) # diagnosticMessage
  126. response_dict['referrals'] = None # referrals
  127. response_dict['saslCreds'] = None # saslCreds
  128. for r in response[3:]:
  129. if r[2] == 3: # referrals
  130. response_dict['referrals'] = referrals_to_list(r[3]) # referrals
  131. else:
  132. response_dict['saslCreds'] = bytes(r[3]) # saslCreds
  133. return response_dict
  134. def sicily_bind_response_to_dict_fast(response):
  135. response_dict = dict()
  136. response_dict['result'] = int(response[0][3]) # resultCode
  137. response_dict['description'] = RESULT_CODES[response_dict['result']]
  138. response_dict['server_creds'] = bytes(response[1][3]) # server_creds
  139. response_dict['error_message'] = to_unicode(response[2][3], from_server=True) # error_message
  140. return response_dict