Skip to content

Commit

Permalink
added certificate configuration options
Browse files Browse the repository at this point in the history
  • Loading branch information
tatankat committed Jan 27, 2023
1 parent 6b60708 commit 1b0c35b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 62 deletions.
3 changes: 3 additions & 0 deletions administrator/language/en-GB/plg_authentication_ldap.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
PLG_AUTHENTICATION_LDAP="Authentication - LDAP"
PLG_LDAP_FIELD_AUTHMETHOD_LABEL="Authorisation Method"
PLG_LDAP_FIELD_BASEDN_LABEL="Base DN"
PLG_LDAP_FIELD_CACERT_LABEL="Path to the server certificate"
PLG_LDAP_FIELD_CACERT_DESC="Full path to the file or directory where Joomla can find the LDAP server's (Certificate Authority) certificate. If this is empty, the system defaults for the TLS_CACERT and TLS_CACERTDIR LDAP client options are used."
PLG_LDAP_FIELD_ENCRYPTION_LABEL="Connection Security"
PLG_LDAP_FIELD_EMAIL_DESC="LDAP attribute which has the User's email address."
PLG_LDAP_FIELD_EMAIL_LABEL="Map: Email"
PLG_LDAP_FIELD_FULLNAME_DESC="LDAP attribute which has the User's full name."
PLG_LDAP_FIELD_FULLNAME_LABEL="Map: Full Name"
PLG_LDAP_FIELD_HOST_LABEL="Host"
PLG_LDAP_FIELD_IGNORE_REQCERT_TLS_LABEL="Ignore Certificate"
PLG_LDAP_FIELD_LDAPDEBUG_DESC="Enables debug hardcoded to level 7"
PLG_LDAP_FIELD_LDAPDEBUG_LABEL="Debug"
PLG_LDAP_FIELD_PASSWORD_DESC="The Connect Password is the password of an administrative account."
Expand Down
24 changes: 23 additions & 1 deletion plugins/authentication/ldap/ldap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
type="radio"
layout="joomla.form.field.radio.switcher"
label="PLG_LDAP_FIELD_V3_LABEL"
default="0"
default="1"
filter="integer"
>
<option value="0">JNO</option>
Expand All @@ -64,6 +64,28 @@
<option value="ssl">PLG_LDAP_FIELD_VALUE_ENCRYPTIONSSL</option>
</field>

<field
name="ignore_reqcert_tls"
type="radio"
label="PLG_LDAP_FIELD_IGNORE_REQCERT_TLS_LABEL"
layout="joomla.form.field.radio.switcher"
default="1"
filter="boolean"
showon="encryption!:none"
>
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>

<field
name="cacert"
type="text"
label="PLG_LDAP_FIELD_CACERT_LABEL"
description="PLG_LDAP_FIELD_CACERT_DESC"
required="false"
showon="encryption!:none[AND]ignore_reqcert_tls:0"
/>

<field
name="no_referrals"
type="radio"
Expand Down
30 changes: 29 additions & 1 deletion plugins/authentication/ldap/src/Extension/Ldap.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,42 @@ public function onUserAuthenticate($credentials, $options, &$response)
$ldap_fullname = $this->params->get('ldap_fullname');
$ldap_uid = $this->params->get('ldap_uid');
$auth_method = $this->params->get('auth_method');
// Load certificate info
$ignore_reqcert_tls = (bool) $this->params->get('ignore_reqcert_tls', '1');
$cacert = $this->params->get('cacert', '');

// getting certificate file and certificate directory options (both need to be set)
if (!$ignore_reqcert_tls && !empty($cacert)) {
if (is_dir($cacert)) {
$cacertdir = $cacert;
$cacertfile = "";
} elseif (is_file($cacert)) {
$cacertfile = $cacert;
$cacertdir = dirname($cacert);
} else {
$cacertfile = $cacert;
$cacertdir = $cacert;
Log::add(sprintf('Certificate path for LDAP client is neither an existing file nor directory: "%s"', $cacert), Log::ERROR, $logcategory);
}
} else {
Log::add(sprintf('Not setting any LDAP TLS CA certificate options because %s, system wide settings are used', $ignore_reqcert_tls ? "certificate is ignored" : "no certificate location is configured"), Log::DEBUG, $logcategory);
}

$options = [
'host' => $this->params->get('host'),
'port' => (int) $this->params->get('port'),
'version' => $this->params->get('use_ldapV3', '0') == '1' ? 3 : 2,
'version' => $this->params->get('use_ldapV3', '1') == '1' ? 3 : 2,
'referrals' => (bool) $this->params->get('no_referrals', '0'),
'encryption' => $this->params->get('encryption', 'none'),
'options' => [
'x_tls_require_cert' => $ignore_reqcert_tls ? LDAP_OPT_X_TLS_NEVER : LDAP_OPT_X_TLS_DEMAND,
],
];
// if these are not set, the system defaults are used
if (isset($cacertdir) && isset($cacertfile)) {
$options['options']['x_tls_cacertdir'] = $cacertdir;
$options['options']['x_tls_cacertfile'] = $cacertfile;
}
Log::add(sprintf('Creating LDAP session with options: %s', json_encode($options)), Log::DEBUG, $logcategory);
$connection_string = sprintf('ldap%s://%s:%s', 'ssl' === $options['encryption'] ? 's' : '', $options['host'], $options['port']);
Log::add(sprintf('Creating LDAP session to connect to "%s" while binding', $connection_string), Log::DEBUG, $logcategory);
Expand Down
69 changes: 9 additions & 60 deletions tests/Integration/Plugin/Authentication/Ldap/LdapPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
/**
* Test class for Ldap plugin
*
* Not testing for:
* * different certificate options
* these can't be properly automically tested as the LDAP_OPT_X_ settings can only be set once in a running process
* * working ldap debug option.
* this can only be tested if phpunit stderr is redirected/duplicated/configured to a file
*
* @package Joomla.UnitTest
* @subpackage Ldap
*
Expand Down Expand Up @@ -73,38 +79,6 @@ private function getPlugin($options): LdapPlugin
return $plugin;
}

private function acceptCertificates(): void
{
//TODO make this (and LDAP_OPT_X_CERTFILE and LDAP_OPT_X_TLS_REQUIRE_CERT) Joomla ldap setting
$cert = JPATH_ROOT . '/' . JTEST_LDAP_CACERTFILE;
ldap_set_option(null, LDAP_OPT_X_TLS_CACERTDIR, dirname($cert));
ldap_set_option(null, LDAP_OPT_X_TLS_CACERTFILE, $cert);
}

private function getAdminConnection(array $options): Ldap
{
$admin_options = [
'host' => $options['host'],
'port' => (int) $options['port'],
'version' => $options['use_ldapV3'] == '1' ? 3 : 2,
'referrals' => (bool) $options['no_referrals'],
'encryption' => $options['encryption'],
'debug' => (bool) $options['ldap_debug'],
];
$ldap = Ldap::create(
'ext_ldap',
$admin_options
);
$ldap->bind("cn=admin,cn=config", "configpassword");
return $ldap;
}

private function requireEncryption($encryption, $options): void
{
//$ldap = $this->getAdminConnection($options);
//TODO configure openldap (only if given permission in phpunit.xml, so people can use their own ldap server) to require the requested encryption to be sure encryption is used
}

private function skipIfAskedFor($options): void
{
if (empty($options["host"])) {
Expand Down Expand Up @@ -137,6 +111,9 @@ public function setUp(): void
'ldap_email' => JTEST_LDAP_EMAIL,
'ldap_uid' => JTEST_LDAP_UID,
'ldap_debug' => 0,
/* the security options can only be set once, these are the best practice settings */
'ignore_reqcert_tls' => 0,
'cacert' => JPATH_ROOT . '/' . JTEST_LDAP_CACERTFILE,
/* changing options to test all code */
'port' => self::LDAPPORT,
'encryption' => "none",
Expand Down Expand Up @@ -236,9 +213,6 @@ public function testOnUserAuthenticateBindAndSearchTLS()
$this->skipIfAskedFor($options);
$plugin = $this->getPlugin($options);

$this->acceptCertificates();
$this->requireEncryption("tls", $options);

$response = new AuthenticationResponse();
$plugin->onUserAuthenticate($this->default_credentials, [], $response);
$this->assertEquals(Authentication::STATUS_SUCCESS, $response->status);
Expand All @@ -260,33 +234,8 @@ public function testOnUserAuthenticateBindAndSearchSSL()
$this->skipIfAskedFor($options);
$plugin = $this->getPlugin($options);

$this->acceptCertificates();
$this->requireEncryption("ssl", $options);

$response = new AuthenticationResponse();
$plugin->onUserAuthenticate($this->default_credentials, [], $response);
$this->assertEquals(Authentication::STATUS_SUCCESS, $response->status);
}

/**
* @testdox does log ldap client calls and errors
* can only be tested if phpunit stderr is redirected/duplicated/configured to a file
* then, we can check if ldap_ calls are present in that file
*
* @return void
*
* @since 4.3.0
*/
/*
public function testOnUserAuthenticateWithDebug()
{
$options = $this->default_options;
$options["ldap_debug"] = 1;
$plugin = $this->getPlugin($options);
$response = new AuthenticationResponse();
$plugin->onUserAuthenticate($this->default_credentials, [], $response);
$this->assertEquals(Authentication::STATUS_SUCCESS, $response->status);
}
*/
}

0 comments on commit 1b0c35b

Please sign in to comment.