nextcloud/apps/user_ldap/tests/ConnectionTest.php

292 lines
7.9 KiB
PHP

<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Jarkko Lehtoranta <devel@jlranta.com>
* @author Joas Schilling <coding@schilljs.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Victor Dubiniuk <dubiniuk@owncloud.com>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\User_LDAP\Tests;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\ILDAPWrapper;
/**
* Class Test_Connection
*
* @group DB
*
* @package OCA\User_LDAP\Tests
*/
class ConnectionTest extends \Test\TestCase {
/** @var \OCA\User_LDAP\ILDAPWrapper|\PHPUnit\Framework\MockObject\MockObject */
protected $ldap;
/** @var Connection */
protected $connection;
protected function setUp(): void {
parent::setUp();
$this->ldap = $this->createMock(ILDAPWrapper::class);
// we use a mock here to replace the cache mechanism, due to missing DI in LDAP backend.
$this->connection = $this->getMockBuilder('OCA\User_LDAP\Connection')
->setMethods(['getFromCache', 'writeToCache'])
->setConstructorArgs([$this->ldap, '', null])
->getMock();
$this->ldap->expects($this->any())
->method('areLDAPFunctionsAvailable')
->willReturn(true);
}
public function testOriginalAgentUnchangedOnClone() {
//background: upon login a bind is done with the user credentials
//which is valid for the whole LDAP resource. It needs to be reset
//to the agent's credentials
$lw = $this->createMock(ILDAPWrapper::class);
$connection = new Connection($lw, '', null);
$agent = [
'ldapAgentName' => 'agent',
'ldapAgentPassword' => '123456',
];
$connection->setConfiguration($agent);
$testConnection = clone $connection;
$user = [
'ldapAgentName' => 'user',
'ldapAgentPassword' => 'password',
];
$testConnection->setConfiguration($user);
$agentName = $connection->ldapAgentName;
$agentPawd = $connection->ldapAgentPassword;
$this->assertSame($agentName, $agent['ldapAgentName']);
$this->assertSame($agentPawd, $agent['ldapAgentPassword']);
}
public function testUseBackupServer() {
$mainHost = 'ldap://nixda.ldap';
$backupHost = 'ldap://fallback.ldap';
$config = [
'ldapConfigurationActive' => true,
'ldapHost' => $mainHost,
'ldapPort' => 389,
'ldapBackupHost' => $backupHost,
'ldapBackupPort' => 389,
'ldapAgentName' => 'uid=agent',
'ldapAgentPassword' => 'SuchASecret'
];
$this->connection->setIgnoreValidation(true);
$this->connection->setConfiguration($config);
$this->ldap->expects($this->any())
->method('isResource')
->willReturn(true);
$this->ldap->expects($this->any())
->method('setOption')
->willReturn(true);
$this->ldap->expects($this->exactly(3))
->method('connect')
->willReturn('ldapResource');
$this->ldap->expects($this->any())
->method('errno')
->willReturn(0);
// Not called often enough? Then, the fallback to the backup server is broken.
$this->connection->expects($this->exactly(4))
->method('getFromCache')
->with('overrideMainServer')
->will($this->onConsecutiveCalls(false, false, true, true));
$this->connection->expects($this->once())
->method('writeToCache')
->with('overrideMainServer', true);
$isThrown = false;
$this->ldap->expects($this->exactly(3))
->method('bind')
->willReturnCallback(function () use (&$isThrown) {
if (!$isThrown) {
$isThrown = true;
throw new \OC\ServerNotAvailableException();
}
return true;
});
$this->connection->init();
$this->connection->resetConnectionResource();
// with the second init() we test whether caching works
$this->connection->init();
}
public function testDontUseBackupServerOnFailedAuth() {
$mainHost = 'ldap://nixda.ldap';
$backupHost = 'ldap://fallback.ldap';
$config = [
'ldapConfigurationActive' => true,
'ldapHost' => $mainHost,
'ldapPort' => 389,
'ldapBackupHost' => $backupHost,
'ldapBackupPort' => 389,
'ldapAgentName' => 'uid=agent',
'ldapAgentPassword' => 'SuchASecret'
];
$this->connection->setIgnoreValidation(true);
$this->connection->setConfiguration($config);
$this->ldap->expects($this->any())
->method('isResource')
->willReturn(true);
$this->ldap->expects($this->any())
->method('setOption')
->willReturn(true);
$this->ldap->expects($this->once())
->method('connect')
->willReturn('ldapResource');
$this->ldap->expects($this->any())
->method('errno')
->willReturn(49);
$this->connection->expects($this->any())
->method('getFromCache')
->with('overrideMainServer')
->willReturn(false);
$this->connection->expects($this->never())
->method('writeToCache');
$this->ldap->expects($this->exactly(1))
->method('bind')
->willReturn(false);
$this->connection->init();
}
public function testBindWithInvalidCredentials() {
// background: Bind with invalid credentials should return false
// and not throw a ServerNotAvailableException.
$host = 'ldap://nixda.ldap';
$config = [
'ldapConfigurationActive' => true,
'ldapHost' => $host,
'ldapPort' => 389,
'ldapBackupHost' => '',
'ldapAgentName' => 'user',
'ldapAgentPassword' => 'password'
];
$this->connection->setIgnoreValidation(true);
$this->connection->setConfiguration($config);
$this->ldap->expects($this->any())
->method('isResource')
->willReturn(true);
$this->ldap->expects($this->any())
->method('setOption')
->willReturn(true);
$this->ldap->expects($this->any())
->method('connect')
->willReturn('ldapResource');
$this->ldap->expects($this->once())
->method('bind')
->willReturn(false);
// LDAP_INVALID_CREDENTIALS
$this->ldap->expects($this->any())
->method('errno')
->willReturn(0x31);
try {
$this->assertFalse($this->connection->bind(), 'Connection::bind() should not return true with invalid credentials.');
} catch (\OC\ServerNotAvailableException $e) {
$this->fail('Failed asserting that exception of type "OC\ServerNotAvailableException" is not thrown.');
}
}
public function testStartTlsNegotiationFailure() {
// background: If Start TLS negotiation fails,
// a ServerNotAvailableException should be thrown.
$host = 'ldap://nixda.ldap';
$port = 389;
$config = [
'ldapConfigurationActive' => true,
'ldapHost' => $host,
'ldapPort' => $port,
'ldapTLS' => true,
'ldapBackupHost' => '',
'ldapAgentName' => 'user',
'ldapAgentPassword' => 'password'
];
$this->connection->setIgnoreValidation(true);
$this->connection->setConfiguration($config);
$this->ldap->expects($this->any())
->method('isResource')
->willReturn(true);
$this->ldap->expects($this->any())
->method('connect')
->willReturn('ldapResource');
$this->ldap->expects($this->any())
->method('setOption')
->willReturn(true);
$this->ldap->expects($this->any())
->method('bind')
->willReturn(true);
$this->ldap->expects($this->any())
->method('errno')
->willReturn(0);
$this->ldap->expects($this->any())
->method('startTls')
->willReturn(false);
$this->expectException(\OC\ServerNotAvailableException::class);
$this->expectExceptionMessage('Start TLS failed, when connecting to LDAP host ' . $host . '.');
$this->connection->init();
}
}