Merge remote-tracking branch 'origin/develop' into retry-tests

This commit is contained in:
Mark Felder 2024-09-16 11:51:22 -04:00
commit e24e107f3d
6 changed files with 58 additions and 29 deletions

1
changelog.d/ldap-ca.add Normal file
View file

@ -0,0 +1 @@
LDAP configuration now permits overriding the CA root certificate file for TLS validation.

1
changelog.d/ldaps.fix Normal file
View file

@ -0,0 +1 @@
LDAPS connections (implicit TLS) are now supported.

View file

@ -619,7 +619,9 @@ config :pleroma, :ldap,
tls: System.get_env("LDAP_TLS") == "true", tls: System.get_env("LDAP_TLS") == "true",
tlsopts: [], tlsopts: [],
base: System.get_env("LDAP_BASE") || "dc=example,dc=com", base: System.get_env("LDAP_BASE") || "dc=example,dc=com",
uid: System.get_env("LDAP_UID") || "cn" uid: System.get_env("LDAP_UID") || "cn",
# defaults to CAStore's Mozilla roots
cacertfile: nil
oauth_consumer_strategies = oauth_consumer_strategies =
System.get_env("OAUTH_CONSUMER_STRATEGIES") System.get_env("OAUTH_CONSUMER_STRATEGIES")

View file

@ -968,12 +968,13 @@ Pleroma account will be created with the same name as the LDAP user name.
* `enabled`: enables LDAP authentication * `enabled`: enables LDAP authentication
* `host`: LDAP server hostname * `host`: LDAP server hostname
* `port`: LDAP port, e.g. 389 or 636 * `port`: LDAP port, e.g. 389 or 636
* `ssl`: true to use SSL, usually implies the port 636 * `ssl`: true to use implicit SSL/TLS, usually port 636
* `sslopts`: additional SSL options * `sslopts`: additional SSL options
* `tls`: true to start TLS, usually implies the port 389 * `tls`: true to use explicit TLS (STARTTLS), usually port 389
* `tlsopts`: additional TLS options * `tlsopts`: additional TLS options
* `base`: LDAP base, e.g. "dc=example,dc=com" * `base`: LDAP base, e.g. "dc=example,dc=com"
* `uid`: LDAP attribute name to authenticate the user, e.g. when "cn", the filter will be "cn=username,base" * `uid`: LDAP attribute name to authenticate the user, e.g. when "cn", the filter will be "cn=username,base"
* `cacertfile`: Path to alternate CA root certificates file
Note, if your LDAP server is an Active Directory server the correct value is commonly `uid: "cn"`, but if you use an Note, if your LDAP server is an Active Directory server the correct value is commonly `uid: "cn"`, but if you use an
OpenLDAP server the value may be `uid: "uid"`. OpenLDAP server the value may be `uid: "uid"`.

View file

@ -40,39 +40,52 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
host = Keyword.get(ldap, :host, "localhost") host = Keyword.get(ldap, :host, "localhost")
port = Keyword.get(ldap, :port, 389) port = Keyword.get(ldap, :port, 389)
ssl = Keyword.get(ldap, :ssl, false) ssl = Keyword.get(ldap, :ssl, false)
sslopts = Keyword.get(ldap, :sslopts, []) tls = Keyword.get(ldap, :tls, false)
tlsopts = Keyword.get(ldap, :tlsopts, []) cacertfile = Keyword.get(ldap, :cacertfile) || CAStore.file_path()
default_secure_opts = [
verify: :verify_peer,
cacerts: decode_certfile(cacertfile),
customize_hostname_check: [
fqdn_fun: fn _ -> to_charlist(host) end
]
]
sslopts = Keyword.merge(default_secure_opts, Keyword.get(ldap, :sslopts, []))
tlsopts = Keyword.merge(default_secure_opts, Keyword.get(ldap, :tlsopts, []))
# :sslopts can only be included in :eldap.open/2 when {ssl: true}
# or the connection will fail
options = options =
[{:port, port}, {:ssl, ssl}, {:timeout, @connection_timeout}] ++ if ssl do
if sslopts != [], do: [{:sslopts, sslopts}], else: [] [{:port, port}, {:ssl, ssl}, {:sslopts, sslopts}, {:timeout, @connection_timeout}]
else
[{:port, port}, {:ssl, ssl}, {:timeout, @connection_timeout}]
end
case :eldap.open([to_charlist(host)], options) do case :eldap.open([to_charlist(host)], options) do
{:ok, connection} -> {:ok, connection} ->
try do try do
if Keyword.get(ldap, :tls, false) do cond do
:application.ensure_all_started(:ssl) ssl ->
:application.ensure_all_started(:ssl)
case :eldap.start_tls( tls ->
connection, case :eldap.start_tls(
Keyword.merge( connection,
[ tlsopts,
verify: :verify_peer, @connection_timeout
cacerts: :certifi.cacerts(), ) do
customize_hostname_check: [ :ok ->
fqdn_fun: fn _ -> to_charlist(host) end :ok
]
],
tlsopts
),
@connection_timeout
) do
:ok ->
:ok
error -> error ->
Logger.error("Could not start TLS: #{inspect(error)}") Logger.error("Could not start TLS: #{inspect(error)}")
end :eldap.close(connection)
end
true ->
:ok
end end
bind_user(connection, ldap, name, password) bind_user(connection, ldap, name, password)
@ -147,4 +160,16 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
error -> error error -> error
end end
end end
defp decode_certfile(file) do
with {:ok, data} <- File.read(file) do
data
|> :public_key.pem_decode()
|> Enum.map(fn {_, b, _} -> b end)
else
_ ->
Logger.error("Unable to read certfile: #{file}")
[]
end
end
end end

View file

@ -204,7 +204,6 @@ defmodule Pleroma.Mixfile do
{:oban_live_dashboard, "~> 0.1.1"}, {:oban_live_dashboard, "~> 0.1.1"},
{:multipart, "~> 0.4.0", optional: true}, {:multipart, "~> 0.4.0", optional: true},
{:argon2_elixir, "~> 4.0"}, {:argon2_elixir, "~> 4.0"},
{:certifi, "~> 2.12"},
## dev & test ## dev & test
{:phoenix_live_reload, "~> 1.3.3", only: :dev}, {:phoenix_live_reload, "~> 1.3.3", only: :dev},