# LDAP library for PHP

`buckhill/ldap` is a utility library for connecting to and querying `LDAP` servers.

## Contents 

- [Installation](#installation)
- [Connecting](#use)
  * [Connecting](#connecting)
  * [Connecting with options](#connecting-with-options)
  * [Using TLS connection](#using-tls-connection)
- [Authentication](#authentication)
  * [With credentials](#authenticating-with-credentials)
  * [Anonymous](#anonymous-bind)
- [Modifying the directory](#modifying-the-directory)
  * [Changing user's password](#changing-users-password)
- [Searching](#searching-the-directory)
  * [Single result](#searching-for-single-result)
  * [Multiple results](#searching-for-multiple-results)

## Installation

`composer require "buckhill/ldap: *"`

## Use

### Connecting 

```php
<?php

use Buckhill\LDAP\Client;

$ldap = new Client('127.0.0.1', 389);

try 
{
	$ldap->connect();
}
catch(\Buckhill\LDAP\Errors\ConnectionError $e)
{
	echo $e->getMessage();
}
```

### Connecting with options 

Third parameter are connection options, it's an array of options so you can specify as many options as you need to.

```php
<?php

use Buckhill\LDAP\Client;

$options = [
	[
		'name' => LDAP_OPT_PROTOCOL_VERSION,
        'value' => 3
	]
];

$ldap = new Client('127.0.0.1', 389, $options);

try 
{
	$ldap->connect();
}
catch(\Buckhill\LDAP\Errors\ConnectionError $e)
{
	echo $e->getMessage();
}
catch(\Buckhill\LDAP\Errors\BadOptionFormatError $e)
{
	// Thrown when options array contains invalid information
	echo $e->getMessage();
}
```


### Using TLS connection

To use TLS, 4th parameter must be set to `true`. If your server doesn't support TLS, an exception will be thrown.

```php
<?php

use Buckhill\LDAP\Client;

$options = [
	[
		'name' => LDAP_OPT_PROTOCOL_VERSION,
        'value' => 3
	]
];

$ldap = new Client('127.0.0.1', 389, $options, true);

try 
{
	$ldap->connect();
}
catch(\Buckhill\LDAP\Errors\ConnectionError $e)
{
	echo $e->getMessage();
}
```


## Authentication

Authentication in LDAP can be anonymous or using credentials. Authentication is also called binding. This library exposes both `bind` and `authenticate` function to avoid confusion, along with utility method called `anonymous` which is used for anonymous binding.

### Authenticating with credentials

```php
<?php

use Buckhill\LDAP\Client;

$ldap = new Client('127.0.0.1', 389, [['name' => LDAP_OPT_PROTOCOL_VERSION, 'value' => 3]]);

$ldap->connect();

$user = 'uid=your_username,ou=users,dc=your_organization,dc=com';
$password = 'your_password';

$result = $ldap->authenticate($user, $password);

if(!$result)
{
	echo 'Error number: '. $ldap->errorNumber();
	echo 'Message: '. $ldap->errorString();
}
```

### Anonymous bind

```php 
<?php

use Buckhill\LDAP\Client;

$ldap = new Client('127.0.0.1', 389, [['name' => LDAP_OPT_PROTOCOL_VERSION, 'value' => 3]]);

$ldap->connect();

$result = $ldap->anonymous();

if($result)
{
	echo 'Success!';
}

```


## Modifying the directory

Modification requires authenticating as administrator first. 

### Changing user's password 

LDAP uses special convention for hasing and storing a password. To ease up the process, this library exposes a method called `getPassword` which returns a string that can be used for altering users' passwords.

```php
<?php

use Buckhill\LDAP\Client;

$ldap = new Client('127.0.0.1', 389, [['name' => LDAP_OPT_PROTOCOL_VERSION, 'value' => 3]]);

try 
{
	$ldap->connect();
	
	$ldap->authenticate('admin_user', 'admin_password'); // Please change these before trying to copy paste :)
		
	$result = $ldap->modify('user_dn_you_want_to_update', ['userPassword' => $ldap->toPassword('this is a new password')]);
	
	if($result)
	{
		echo 'Success!';
	}
	else	
	{
		echo $ldap->errorString();
	}
}
catch(\Buckhill\LDAP\Errors\ConnectionError $e)
{
}
```

## Searching the directory

Results of directory search are returned as instances of `EntryCollection` class.

### Searching for single result

```
<?php

use Buckhill\LDAP\Client;

$ldap = new Client('127.0.0.1', 389, [['name' => LDAP_OPT_PROTOCOL_VERSION, 'value' => 3]]);

try 
{
	$ldap->connect();
	
	$ldap->authenticate('your_dn', 'your_password');
	
	// Required so we know which directory we're searching
	$base_dn = 'ou=users,dc=buckhill,dc=co,dc=uk';
	
	// This is what you're going to search for
	$filter = 'uid=nikola@buckhill.co.uk';
	
	// The attributes you want to receive back
	$attributes = ['memberof', 'cn', 'dn', 'mail'];
	
	$result = $ldap->search($dn, $filter, $attributes);
	
	if(!$result instanceof \Buckhill\LDAP\EntryCollection)
	{
		echo 'There are no results for your search criteria';
	}
	else
	{
		// check how many attributes we got back
		echo 'Number of attributes: ' . $result->size();
		
		// Fetch an attribute and display its value
		echo 'Attribute: mail, value: '. $result->get('mail')->getValue();
		
		// Some attributes can have multiple values, such as memberof. An array of values is returned for such an attribute
		print_r($result->get('memberof')->getValue()); 
		
		// You can also check if an attribute is present before fetching it
		if($result->has('id'))
		{
			echo 'id atribute is present!';
		}
		
	}
}
catch(\Buckhill\LDAP\Errors\ConnectionError $e)
{
}
```


### Searching for multiple results 

Searching for multiple results is the same as searching for single result. The difference is that an array of collections is returned

```php
<?php


use Buckhill\LDAP\Client;

$ldap = new Client('127.0.0.1', 389, [['name' => LDAP_OPT_PROTOCOL_VERSION, 'value' => 3]]);

try 
{
	$ldap->connect();
	
	$ldap->authenticate('your_dn', 'your_password');
	
	// Required so we know which directory we're searching
	$base_dn = 'ou=users,dc=buckhill,dc=co,dc=uk';
	
	// This is what you're going to search for. Wildcards are at the END, not at the beginning!
	$filter = 'uid=nikola*';
	
	// The attributes you want to receive back
	$attributes = ['memberof', 'cn', 'dn', 'mail'];
	
	// If there's 1 record, result is an instance of EntryCollection
	// If there are multiple records, the result is an array of EntryCollection
	// If there are no records, the result is an empty array	
	$result = $ldap->search($dn, $filter, $attributes);
	
	if($result instanceof \Buckhill\LDAP\EntryCollection)
	{
		echo 'Found: '. $result->get('mail')->getValue();
	}
	elseif(is_array($result) && sizeof($result))
	{
		foreach($result as $collection)
		{
			// $collection is an instance of \Buckhill\LDAP\EntryCollection
		}
	}
	else
	{
		echo 'There are no results for your query';
	}
}
catch(\Buckhill\LDAP\Errors\ConnectionError $e)
{
}

```
