logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

ldap_authenticator.ex (3638B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.Auth.LDAPAuthenticator do
  5. alias Pleroma.User
  6. require Logger
  7. import Pleroma.Web.Auth.Helpers, only: [fetch_credentials: 1, fetch_user: 1]
  8. @behaviour Pleroma.Web.Auth.Authenticator
  9. @base Pleroma.Web.Auth.PleromaAuthenticator
  10. @connection_timeout 10_000
  11. @search_timeout 10_000
  12. defdelegate get_registration(conn), to: @base
  13. defdelegate create_from_registration(conn, registration), to: @base
  14. defdelegate handle_error(conn, error), to: @base
  15. defdelegate auth_template, to: @base
  16. defdelegate oauth_consumer_template, to: @base
  17. def get_user(%Plug.Conn{} = conn) do
  18. with {:ldap, true} <- {:ldap, Pleroma.Config.get([:ldap, :enabled])},
  19. {:ok, {name, password}} <- fetch_credentials(conn),
  20. %User{} = user <- ldap_user(name, password) do
  21. {:ok, user}
  22. else
  23. {:ldap, _} ->
  24. @base.get_user(conn)
  25. error ->
  26. error
  27. end
  28. end
  29. defp ldap_user(name, password) do
  30. ldap = Pleroma.Config.get(:ldap, [])
  31. host = Keyword.get(ldap, :host, "localhost")
  32. port = Keyword.get(ldap, :port, 389)
  33. ssl = Keyword.get(ldap, :ssl, false)
  34. sslopts = Keyword.get(ldap, :sslopts, [])
  35. options =
  36. [{:port, port}, {:ssl, ssl}, {:timeout, @connection_timeout}] ++
  37. if sslopts != [], do: [{:sslopts, sslopts}], else: []
  38. case :eldap.open([to_charlist(host)], options) do
  39. {:ok, connection} ->
  40. try do
  41. if Keyword.get(ldap, :tls, false) do
  42. :application.ensure_all_started(:ssl)
  43. case :eldap.start_tls(
  44. connection,
  45. Keyword.get(ldap, :tlsopts, []),
  46. @connection_timeout
  47. ) do
  48. :ok ->
  49. :ok
  50. error ->
  51. Logger.error("Could not start TLS: #{inspect(error)}")
  52. end
  53. end
  54. bind_user(connection, ldap, name, password)
  55. after
  56. :eldap.close(connection)
  57. end
  58. {:error, error} ->
  59. Logger.error("Could not open LDAP connection: #{inspect(error)}")
  60. {:error, {:ldap_connection_error, error}}
  61. end
  62. end
  63. defp bind_user(connection, ldap, name, password) do
  64. uid = Keyword.get(ldap, :uid, "cn")
  65. base = Keyword.get(ldap, :base)
  66. case :eldap.simple_bind(connection, "#{uid}=#{name},#{base}", password) do
  67. :ok ->
  68. case fetch_user(name) do
  69. %User{} = user ->
  70. user
  71. _ ->
  72. register_user(connection, base, uid, name)
  73. end
  74. error ->
  75. error
  76. end
  77. end
  78. defp register_user(connection, base, uid, name) do
  79. case :eldap.search(connection, [
  80. {:base, to_charlist(base)},
  81. {:filter, :eldap.equalityMatch(to_charlist(uid), to_charlist(name))},
  82. {:scope, :eldap.wholeSubtree()},
  83. {:timeout, @search_timeout}
  84. ]) do
  85. {:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _}} ->
  86. params = %{
  87. name: name,
  88. nickname: name,
  89. password: nil
  90. }
  91. params =
  92. case List.keyfind(attributes, 'mail', 0) do
  93. {_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail))
  94. _ -> params
  95. end
  96. changeset = User.register_changeset_ldap(%User{}, params)
  97. case User.register(changeset) do
  98. {:ok, user} -> user
  99. error -> error
  100. end
  101. error ->
  102. error
  103. end
  104. end
  105. end