Skip to content

Commit

Permalink
LDAP: Updated default user filter placeholder format
Browse files Browse the repository at this point in the history
To not conflict with env variables, and to align with placeholders used
for PDF gen command.
Added test to cover, including old format supported for
back-compatibility.
For BookStackApp#4967
  • Loading branch information
ssddanbrown committed Apr 28, 2024
1 parent e1149a2 commit 6b68196
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .env.example.complete
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ LDAP_SERVER=false
LDAP_BASE_DN=false
LDAP_DN=false
LDAP_PASS=false
LDAP_USER_FILTER=false
LDAP_USER_FILTER="(&(uid={user}))"
LDAP_VERSION=false
LDAP_START_TLS=false
LDAP_TLS_INSECURE=false
Expand Down
9 changes: 7 additions & 2 deletions app/Access/LdapService.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,18 @@ protected function parseServerString(string $serverString): string

/**
* Build a filter string by injecting common variables.
* Both "${var}" and "{var}" style placeholders are supported.
* Dollar based are old format but supported for compatibility.
*/
protected function buildFilter(string $filterString, array $attrs): string
{
$newAttrs = [];
foreach ($attrs as $key => $attrText) {
$newKey = '${' . $key . '}';
$newAttrs[$newKey] = $this->ldap->escape($attrText);
$escapedText = $this->ldap->escape($attrText);
$oldVarKey = '${' . $key . '}';
$newVarKey = '{' . $key . '}';
$newAttrs[$oldVarKey] = $escapedText;
$newAttrs[$newVarKey] = $escapedText;
}

return strtr($filterString, $newAttrs);
Expand Down
2 changes: 1 addition & 1 deletion app/Config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
'dn' => env('LDAP_DN', false),
'pass' => env('LDAP_PASS', false),
'base_dn' => env('LDAP_BASE_DN', false),
'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))'),
'user_filter' => env('LDAP_USER_FILTER', '(&(uid={user}))'),
'version' => env('LDAP_VERSION', false),
'id_attribute' => env('LDAP_ID_ATTRIBUTE', 'uid'),
'email_attribute' => env('LDAP_EMAIL_ATTRIBUTE', 'mail'),
Expand Down
34 changes: 33 additions & 1 deletion tests/Auth/LdapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function setUp(): void
'services.ldap.id_attribute' => 'uid',
'services.ldap.user_to_groups' => false,
'services.ldap.version' => '3',
'services.ldap.user_filter' => '(&(uid=${user}))',
'services.ldap.user_filter' => '(&(uid={user}))',
'services.ldap.follow_referrals' => false,
'services.ldap.tls_insecure' => false,
'services.ldap.thumbnail_attribute' => null,
Expand Down Expand Up @@ -178,6 +178,38 @@ public function test_a_custom_uid_attribute_can_be_specified_and_is_used_properl
$this->assertDatabaseHas('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => 'cooluser456']);
}

public function test_user_filter_default_placeholder_format()
{
config()->set('services.ldap.user_filter', '(&(uid={user}))');
$this->mockUser->name = 'barryldapuser';
$expectedFilter = '(&(uid=\62\61\72\72\79\6c\64\61\70\75\73\65\72))';

$this->commonLdapMocks(1, 1, 1, 1, 1);
$this->mockLdap->shouldReceive('searchAndGetEntries')
->once()
->with($this->resourceId, config('services.ldap.base_dn'), $expectedFilter, \Mockery::type('array'))
->andReturn(['count' => 0, 0 => []]);

$resp = $this->mockUserLogin();
$resp->assertRedirect('/login');
}

public function test_user_filter_old_placeholder_format()
{
config()->set('services.ldap.user_filter', '(&(username=${user}))');
$this->mockUser->name = 'barryldapuser';
$expectedFilter = '(&(username=\62\61\72\72\79\6c\64\61\70\75\73\65\72))';

$this->commonLdapMocks(1, 1, 1, 1, 1);
$this->mockLdap->shouldReceive('searchAndGetEntries')
->once()
->with($this->resourceId, config('services.ldap.base_dn'), $expectedFilter, \Mockery::type('array'))
->andReturn(['count' => 0, 0 => []]);

$resp = $this->mockUserLogin();
$resp->assertRedirect('/login');
}

public function test_initial_incorrect_credentials()
{
$this->commonLdapMocks(1, 1, 1, 0, 1);
Expand Down

0 comments on commit 6b68196

Please sign in to comment.