Нет описания

ldap_handler.py 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. # IRIS Source Code
  2. # contact@dfir-iris.org
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Lesser General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 3 of the License, or (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # Lesser General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Lesser General Public License
  15. # along with this program; if not, write to the Free Software Foundation,
  16. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. import random
  18. import string
  19. import ldap3.core.exceptions
  20. import ssl
  21. from ldap3 import Connection
  22. from ldap3 import Server
  23. from ldap3 import Tls
  24. from ldap3.utils import conv
  25. from app import app
  26. from app.datamgmt.manage.manage_users_db import get_active_user_by_login
  27. from app.datamgmt.manage.manage_users_db import create_user
  28. from app.datamgmt.manage.manage_users_db import add_user_to_group
  29. from app.datamgmt.manage.manage_groups_db import get_group_by_name
  30. log = app.logger
  31. def _get_unique_identifier(user_login):
  32. if app.config.get('LDAP_AUTHENTICATION_TYPE').lower() == 'ntlm':
  33. return user_login[user_login.find('\\')+1:]
  34. return user_login
  35. def _provision_user(connection, user_login):
  36. if get_active_user_by_login(user_login):
  37. return
  38. search_base = app.config.get('LDAP_SEARCH_DN')
  39. attribute_unique_identifier = app.config.get('LDAP_ATTRIBUTE_IDENTIFIER')
  40. unique_identifier = conv.escape_filter_chars(_get_unique_identifier(user_login))
  41. attribute_display_name = app.config.get('LDAP_ATTRIBUTE_DISPLAY_NAME')
  42. attribute_mail = app.config.get('LDAP_ATTRIBUTE_MAIL')
  43. attributes = []
  44. if attribute_display_name:
  45. attributes.append(attribute_display_name)
  46. if attribute_mail:
  47. attributes.append(attribute_mail)
  48. connection.search(search_base, f'({attribute_unique_identifier}={unique_identifier})', attributes=attributes)
  49. entry = connection.entries[0]
  50. if attribute_display_name:
  51. user_name = entry[attribute_display_name].value
  52. else:
  53. user_name = user_login
  54. if attribute_mail:
  55. user_email = entry[attribute_mail].value
  56. else:
  57. user_email = f'{user_login}@ldap'
  58. log.info(f'Provisioning user "{user_login}" which is present in LDAP but not yet in database.')
  59. # TODO the user password is chosen randomly
  60. # ideally it should be possible to create a user without providing any password
  61. # TODO to create the user password, we use the same code as the one to generate the administrator password in post_init.py
  62. # => should factor and reuse this code bit as a function
  63. # => also, it should probably be more secure to use the secrets module (instead of random)
  64. password = ''.join(random.choices(string.printable[:-6], k=16))
  65. # TODO It seems email unicity is required (a fixed email causes a problem at the second account creation)
  66. # The email either comes from the ldap or is forged from the login to ensure unicity
  67. user = create_user(user_name, user_login, password, user_email, True)
  68. initial_group = get_group_by_name(app.config.get('IRIS_NEW_USERS_DEFAULT_GROUP'))
  69. add_user_to_group(user.id, initial_group.group_id)
  70. def ldap_authenticate(ldap_user_name, ldap_user_pwd):
  71. """
  72. Authenticate to the LDAP server
  73. """
  74. if app.config.get('LDAP_AUTHENTICATION_TYPE').lower() != 'ntlm':
  75. ldap_user_name = conv.escape_filter_chars(ldap_user_name)
  76. ldap_user = f"{app.config.get('LDAP_USER_PREFIX')}{ldap_user_name.strip()}{ ','+app.config.get('LDAP_USER_SUFFIX') if app.config.get('LDAP_USER_SUFFIX') else ''}"
  77. else:
  78. ldap_user = f"{ldap_user_name.strip()}"
  79. if app.config.get('LDAP_CUSTOM_TLS_CONFIG') is True:
  80. tls_configuration = Tls(validate=ssl.CERT_REQUIRED,
  81. version=app.config.get('LDAP_TLS_VERSION'),
  82. local_certificate_file=app.config.get('LDAP_SERVER_CERTIFICATE'),
  83. local_private_key_file=app.config.get('LDAP_PRIVATE_KEY'),
  84. local_private_key_password=app.config.get('LDAP_PRIVATE_KEY_PASSWORD'),
  85. ca_certs_file=app.config.get('LDAP_CA_CERTIFICATE')
  86. )
  87. server = Server(f'{app.config.get("LDAP_CONNECT_STRING")}',
  88. use_ssl=app.config.get('LDAP_USE_SSL'),
  89. tls=tls_configuration)
  90. else:
  91. server = Server(f'{app.config.get("LDAP_CONNECT_STRING")}',
  92. use_ssl=app.config.get('LDAP_USE_SSL'))
  93. conn = Connection(server,
  94. user=ldap_user,
  95. password=ldap_user_pwd,
  96. auto_referrals=False,
  97. authentication=app.config.get('LDAP_AUTHENTICATION_TYPE'))
  98. try:
  99. if not conn.bind():
  100. log.error(f"Cannot bind to ldap server: {conn.last_error} ")
  101. return False
  102. if app.config.get('AUTHENTICATION_CREATE_USER_IF_NOT_EXIST'):
  103. _provision_user(conn, ldap_user_name)
  104. except ldap3.core.exceptions.LDAPInvalidCredentialsResult as e:
  105. log.error(f'Wrong credentials. Error : {e.__str__()}')
  106. return False
  107. except Exception as e:
  108. raise Exception(e.__str__())
  109. log.info("Successful authenticated user")
  110. return True