2014-03-21 14:31:30 +00:00
|
|
|
<?php
|
|
|
|
/**
|
2016-07-21 14:49:16 +00:00
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
|
|
*
|
2016-05-26 17:56:05 +00:00
|
|
|
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
2017-11-06 14:56:42 +00:00
|
|
|
* @author Jarkko Lehtoranta <devel@jlranta.com>
|
2016-07-21 14:49:16 +00:00
|
|
|
* @author Joas Schilling <coding@schilljs.com>
|
2015-03-26 10:44:34 +00:00
|
|
|
* @author Morris Jobke <hey@morrisjobke.de>
|
2017-11-06 14:56:42 +00:00
|
|
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
2016-01-12 14:02:16 +00:00
|
|
|
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
2017-11-06 14:56:42 +00:00
|
|
|
* @author Victor Dubiniuk <dubiniuk@owncloud.com>
|
2015-03-26 10:44:34 +00:00
|
|
|
*
|
|
|
|
* @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/>
|
|
|
|
*
|
|
|
|
*/
|
2015-02-26 10:37:37 +00:00
|
|
|
|
2016-05-12 15:14:59 +00:00
|
|
|
namespace OCA\User_LDAP\Tests;
|
2016-05-12 14:35:33 +00:00
|
|
|
use OCA\User_LDAP\Connection;
|
2016-09-02 09:02:12 +00:00
|
|
|
use OCA\User_LDAP\ILDAPWrapper;
|
2014-03-21 14:31:30 +00:00
|
|
|
|
2015-11-25 15:58:54 +00:00
|
|
|
/**
|
|
|
|
* Class Test_Connection
|
|
|
|
*
|
|
|
|
* @group DB
|
|
|
|
*
|
2016-05-12 15:14:59 +00:00
|
|
|
* @package OCA\User_LDAP\Tests
|
2015-11-25 15:58:54 +00:00
|
|
|
*/
|
2016-05-12 15:14:59 +00:00
|
|
|
class ConnectionTest extends \Test\TestCase {
|
2018-06-27 21:09:44 +00:00
|
|
|
/** @var \OCA\User_LDAP\ILDAPWrapper|\PHPUnit_Framework_MockObject_MockObject */
|
2016-03-15 23:45:30 +00:00
|
|
|
protected $ldap;
|
|
|
|
|
|
|
|
/** @var Connection */
|
|
|
|
protected $connection;
|
|
|
|
|
|
|
|
public function setUp() {
|
|
|
|
parent::setUp();
|
|
|
|
|
2016-09-02 09:02:12 +00:00
|
|
|
$this->ldap = $this->createMock(ILDAPWrapper::class);
|
2016-03-15 23:45:30 +00:00
|
|
|
// we use a mock here to replace the cache mechanism, due to missing DI in LDAP backend.
|
2016-05-12 14:35:33 +00:00
|
|
|
$this->connection = $this->getMockBuilder('OCA\User_LDAP\Connection')
|
2016-09-27 20:54:37 +00:00
|
|
|
->setMethods(['getFromCache', 'writeToCache'])
|
|
|
|
->setConstructorArgs([$this->ldap, '', null])
|
|
|
|
->getMock();
|
2016-03-15 23:45:30 +00:00
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('areLDAPFunctionsAvailable')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
}
|
2014-03-21 14:31:30 +00:00
|
|
|
|
|
|
|
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
|
2016-09-02 09:02:12 +00:00
|
|
|
$lw = $this->createMock(ILDAPWrapper::class);
|
2014-03-21 14:31:30 +00:00
|
|
|
|
2016-03-15 23:45:30 +00:00
|
|
|
$connection = new Connection($lw, '', null);
|
2014-03-21 14:31:30 +00:00
|
|
|
$agent = array(
|
|
|
|
'ldapAgentName' => 'agent',
|
|
|
|
'ldapAgentPassword' => '123456',
|
|
|
|
);
|
|
|
|
$connection->setConfiguration($agent);
|
|
|
|
|
|
|
|
$testConnection = clone $connection;
|
|
|
|
$user = array(
|
|
|
|
'ldapAgentName' => 'user',
|
|
|
|
'ldapAgentPassword' => 'password',
|
|
|
|
);
|
|
|
|
$testConnection->setConfiguration($user);
|
|
|
|
|
|
|
|
$agentName = $connection->ldapAgentName;
|
|
|
|
$agentPawd = $connection->ldapAgentPassword;
|
|
|
|
|
|
|
|
$this->assertSame($agentName, $agent['ldapAgentName']);
|
|
|
|
$this->assertSame($agentPawd, $agent['ldapAgentPassword']);
|
|
|
|
}
|
|
|
|
|
2016-03-15 23:45:30 +00:00
|
|
|
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')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('setOption')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
2018-07-13 07:16:57 +00:00
|
|
|
$this->ldap->expects($this->exactly(3))
|
2016-03-15 23:45:30 +00:00
|
|
|
->method('connect')
|
|
|
|
->will($this->returnValue('ldapResource'));
|
|
|
|
|
2017-06-20 01:46:35 +00:00
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('errno')
|
|
|
|
->will($this->returnValue(0));
|
|
|
|
|
2016-03-15 23:45:30 +00:00
|
|
|
// Not called often enough? Then, the fallback to the backup server is broken.
|
2018-07-13 07:16:57 +00:00
|
|
|
$this->connection->expects($this->exactly(4))
|
2016-03-15 23:45:30 +00:00
|
|
|
->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')
|
|
|
|
->will($this->returnCallback(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();
|
|
|
|
}
|
|
|
|
|
2018-06-27 21:09:44 +00:00
|
|
|
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')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('setOption')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->once())
|
|
|
|
->method('connect')
|
|
|
|
->will($this->returnValue('ldapResource'));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('errno')
|
|
|
|
->will($this->returnValue(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();
|
|
|
|
}
|
|
|
|
|
2017-07-17 16:12:43 +00:00
|
|
|
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')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('setOption')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('connect')
|
|
|
|
->will($this->returnValue('ldapResource'));
|
|
|
|
|
2018-02-22 11:45:28 +00:00
|
|
|
$this->ldap->expects($this->once())
|
2017-07-17 16:12:43 +00:00
|
|
|
->method('bind')
|
|
|
|
->will($this->returnValue(false));
|
|
|
|
|
|
|
|
// LDAP_INVALID_CREDENTIALS
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('errno')
|
|
|
|
->will($this->returnValue(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.');
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 16:14:13 +00:00
|
|
|
|
|
|
|
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')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('connect')
|
|
|
|
->will($this->returnValue('ldapResource'));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('setOption')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('bind')
|
|
|
|
->will($this->returnValue(true));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('errno')
|
|
|
|
->will($this->returnValue(0));
|
|
|
|
|
|
|
|
$this->ldap->expects($this->any())
|
|
|
|
->method('startTls')
|
|
|
|
->will($this->returnValue(false));
|
|
|
|
|
|
|
|
$this->expectException(\OC\ServerNotAvailableException::class);
|
|
|
|
$this->expectExceptionMessage('Start TLS failed, when connecting to LDAP host ' . $host . '.');
|
|
|
|
|
|
|
|
$this->connection->init();
|
|
|
|
}
|
|
|
|
|
2015-11-25 15:58:54 +00:00
|
|
|
}
|