| @@ -0,0 +1,72 @@ | ||
| ## Description | ||
|
|
||
| > **ATTENTION**: Version v5.0.0 is in heavy development, however it is close to completion. Use 'dev-master' at you're own risk. | ||
| adLDAP is a tested PHP class library that provides LDAP authentication and Active Directory management tools. | ||
|
|
||
| ## Index | ||
|
|
||
| > **Note:** Documentation is incomplete as Adldap is currently in the upgrade process to version `5.0.0`. They will be fully featured and complete in the coming weeks. | ||
| - [Installation](#installation) | ||
| - [Testing With A Public AD Server](#need-to-test-an-ldap-connection) | ||
| - [Upgrading to v5 from v4](docs/UPGRADING.md) | ||
| - [Getting Started](docs/GETTING-STARTED.md) | ||
| - Usage | ||
| - [Search Functions](docs/SEARCH-FUNCTIONS.md) | ||
| - [Computer Functions](docs/COMPUTER-FUNCTIONS.md) | ||
| - [Contact Functions](docs/CONTACT-FUNCTIONS.md) | ||
| - [Exchange Functions](docs/EXCHANGE-FUNCTIONS.md) | ||
| - [Folder Functions](docs/FOLDER-FUNCTIONS.md) | ||
| - [Group Functions](docs/GROUP-FUNCTIONS.md) | ||
| - [User Functions](docs/USER-FUNCTIONS.md) | ||
|
|
||
| ## Requirements | ||
|
|
||
| To use adLDAP, your sever must support: | ||
|
|
||
| - PHP 5.4 or greater | ||
| - PHP LDAP Extension | ||
|
|
||
|
|
||
| ## Optional Requirements | ||
|
|
||
| If your AD server requires SSL, your server must support the following libraries: | ||
|
|
||
| - PHP SSL Libraries (http://php.net/openssl) | ||
|
|
||
| ## Installation | ||
|
|
||
| adLDAP has moved to a composer based installation. If you'd like to use adLDAP without an auto-loader, you'll | ||
| have to require the files inside the project `src/` directory yourself. | ||
|
|
||
| Insert Adldap into your `composer.json` file: | ||
|
|
||
| "adldap/adldap": "5.0.*" | ||
|
|
||
| Run `composer update` | ||
|
|
||
| You're good to go! | ||
|
|
||
| ## Need to test an LDAP connection? | ||
|
|
||
| If you need to test something with access to an LDAP server, the generous folks at [Georgia Tech](http://drupal.gatech.edu/handbook/public-ldap-server) have you covered. | ||
|
|
||
| Use the following configuration: | ||
|
|
||
| $config = array( | ||
| 'account_suffix' => "@gatech.edu", | ||
|
|
||
| 'domain_controllers' => array("whitepages.gatech.edu"), | ||
|
|
||
| 'base_dn' => 'dc=whitepages,dc=gatech,dc=edu', | ||
|
|
||
| 'admin_username' => '', | ||
|
|
||
| 'admin_password' => '', | ||
| ); | ||
|
|
||
| $ad = new Adldap($config); | ||
|
|
||
| However while useful for basic testing, the queryable data only includes user data, so if you're looking for testing with any other information | ||
| or functionality such as modification, you'll have to use you're own server. |
| @@ -0,0 +1,53 @@ | ||
| { | ||
| "name": "adldap/adldap", | ||
| "type": "library", | ||
| "description": "A PHP LDAP Library for Active Directory Manipulation", | ||
| "keywords": [ | ||
| "active directory", | ||
| "ldap", | ||
| "windows" | ||
| ], | ||
| "license": "LGPL-2.1", | ||
| "support": { | ||
| "issues": "https://github.com/adldap/adLDAP/issues", | ||
| "source": "https://github.com/adldap/adLDAP" | ||
| }, | ||
| "authors": [ | ||
| { | ||
| "name": "Richard Hyland", | ||
| "email": "adldap@richardhyland.com", | ||
| "role": "Developer" | ||
| }, | ||
| { | ||
| "name": "Scott Barnett", | ||
| "email": "scott@wiggumworld.com", | ||
| "role": "Developer" | ||
| }, | ||
| { | ||
| "name": "Steve Bauman", | ||
| "email": "steven_bauman@outlook.com", | ||
| "role": "Developer" | ||
| } | ||
| ], | ||
| "require": { | ||
| "php": ">=5.4.0", | ||
| "ext-ldap": "*" | ||
| }, | ||
| "require-dev": { | ||
| "phpunit/phpunit": "4.6.*", | ||
| "mockery/mockery": "0.9.*" | ||
| }, | ||
| "archive": { | ||
| "exclude": ["/examples", "/tests"] | ||
| }, | ||
| "autoload": { | ||
| "psr-4": { | ||
| "Adldap\\": "src/" | ||
| } | ||
| }, | ||
| "autoload-dev": { | ||
| "psr-4": { | ||
| "Adldap\\Tests\\": "tests/" | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,51 @@ | ||
| ## Computer Functions | ||
|
|
||
| ### All | ||
|
|
||
| To retrieve all computers on your AD server, use the `all()` method: | ||
|
|
||
| $results = $ad->computer()->all(); | ||
|
|
||
| You can also customize your results by providing some paramters inside the function like so: | ||
|
|
||
| $fields = array('operatingsystem'); | ||
|
|
||
| $results = $ad->computer()->all($fields, $sorted = true, $sortBy = 'cn', $sortByDirection = 'asc'); | ||
|
|
||
| ### Find | ||
|
|
||
| To retrieve information on a specific computer, use the `find()` method: | ||
|
|
||
| $computer = $ad->computer->find('WIN-PC'); | ||
|
|
||
| You can also customize the fields that are returned by passing in field array in the second parameter: | ||
|
|
||
| $fields = array('operatingAystem', 'operatingsystemversion'); | ||
|
|
||
| $computer = $ad->computer()->find('WIN-PC', $fields); | ||
|
|
||
| ### Info | ||
|
|
||
| To preserve backwards compatibility, the `info()` function is an alias for the `find()` method: | ||
|
|
||
| $computer = $ad->computer()->info('WIN-PC', $fields); | ||
|
|
||
| ### DN | ||
|
|
||
| To retrieve a computers distinguished name, use the `dn()` method: | ||
|
|
||
| $computerDn = $ad->computer()->dn('WIN-PC'); | ||
|
|
||
| echo $computerDn; | ||
|
|
||
| ### Groups | ||
|
|
||
| To retrieve all the groups that a computer is in, use the `groups()` method: | ||
|
|
||
| $groups = $ad->computer()->groups('WIN-PC'); | ||
|
|
||
| ### In Group | ||
|
|
||
| To determine if a computer is in a group, use the `inGroup()` method: | ||
|
|
||
| $inGroup = $ad->computer()->inGroup('WIN-PC', 'Accounting'); // Returns true / false |
| @@ -0,0 +1,2 @@ | ||
| ## Configuration | ||
|
|
| @@ -0,0 +1,55 @@ | ||
| ## Contact Functions | ||
|
|
||
| ### All | ||
|
|
||
| To retrieve all contacts from AD, use the `all()` method: | ||
|
|
||
| $contacts = $ad->contact()->all(); | ||
|
|
||
| ### Find | ||
|
|
||
| To retrieve information on a specific contact, use the `find()` method: | ||
|
|
||
| $contact = $ad->contact()->find('John Doe'); | ||
|
|
||
| If you're only interested in certain LDAP fields, insert your fields in the second parameter: | ||
|
|
||
| $fields = [ | ||
| 'cn' | ||
| ]; | ||
|
|
||
| $contact = $ad->contact()->find('John Doe', $fields); | ||
|
|
||
| ### Info | ||
|
|
||
| The `info()` method is an alias for the `find()` method: | ||
|
|
||
| $contact = $ad->contact()->info('John Doe', $fields); | ||
|
|
||
| ### DN | ||
|
|
||
| To retrieve a contacts DN, use the `dn()` method: | ||
|
|
||
| $contactDn = $ad->contact()->dn('John Doe'); | ||
|
|
||
| echo $contactDn; | ||
|
|
||
| ### Create | ||
|
|
||
| ### Modify | ||
|
|
||
| ### Delete | ||
|
|
||
| To delete a contact, use the `delete()` method: | ||
|
|
||
| $contactDn = $ad->contact()->dn('John Doe'); | ||
|
|
||
| if($contactDn) { | ||
| $deleted = $ad->contact()->delete($contactDn); | ||
| } | ||
|
|
||
| ### Groups | ||
|
|
||
| ### In Group | ||
|
|
||
| ### Contact Mail Enable |
| @@ -0,0 +1,41 @@ | ||
| ## Exchange Functions | ||
|
|
||
| ### All | ||
|
|
||
| To retrieve all exchange servers on your AD, use the `all()` method: | ||
|
|
||
| $servers = $ad->exchange()->all(); | ||
|
|
||
| You can also sort your results: | ||
|
|
||
| $fields = ['cn', 'distinguishedname']; | ||
|
|
||
| $sorted = true; | ||
|
|
||
| $sortBy = 'cn'; | ||
|
|
||
| $sortDirection = 'desc'; | ||
|
|
||
| $servers = $ad->exchange()->all($fields, $sorted, $sortBy, $sortDirection); | ||
|
|
||
| ### Find | ||
|
|
||
| To retrieve information on an exchange server, use the `find()` method: | ||
|
|
||
| $serverName = 'EXCH-CORP'; | ||
|
|
||
| $server = $ad->exchange()->find($serverName); | ||
|
|
||
| ### Create Mailbox | ||
|
|
||
| ### Storage Groups | ||
|
|
||
| ### Servers | ||
|
|
||
| The `servers()` method is an alias for the `all()` method, this is purely for backwards compatibility. | ||
|
|
||
| $servers = $ad->exchange()->servers(); | ||
|
|
||
| ### Add Address | ||
|
|
||
| ### Add X 400 |
| @@ -0,0 +1,69 @@ | ||
| ## Folder Functions | ||
|
|
||
| Folder functions are used for managing OU's (organizational units). | ||
|
|
||
| ### All | ||
|
|
||
| To retrieve all OU's from AD, use the `all()` method: | ||
|
|
||
| $folders = $ad->folder()->all(); | ||
|
|
||
| Keep in mind that this query is by default recursive, and your results may be limited depending on your server. | ||
|
|
||
| ### Listing | ||
|
|
||
| listing($folders = array(), $dnType = Adldap::ADLDAP_FOLDER, $recursive = NULL, $type = NULL) | ||
|
|
||
| To retrieve an OU's (organizational unit(s)) listing, use the `listing()` function. However keep in mind that this query is by default recursive! | ||
| Calling this function without listing an OU will retrieve all entries recursively. | ||
|
|
||
| Retrieving all data from your base DN (**not recommended if you have a large AD**): | ||
|
|
||
| $results = $ad->folder()->listing(); | ||
|
|
||
| Retrieving all data from the OU `Acme`: | ||
|
|
||
| $results = $ad->folder()->listing(array('Acme')); | ||
|
|
||
| To navigate an OU, pass in deeper OUs into the array. For example: | ||
|
|
||
| $results = $ad->folder()->listing(array('Acme', 'Users', 'Accounting')); | ||
|
|
||
| // The searched DN would be: 'OU=Accounting,OU=Users,OU=Acme,DC=corp,DC=acme,DC=com' | ||
|
|
||
| It's also good to note, that **OUs must be spelt exact**. If an OU is not spelled correctly, you will receive zero results. | ||
|
|
||
| ### Find | ||
|
|
||
| To find a folder, use the `find()` method: | ||
|
|
||
| $folder = $ad->folder()->find('Accounting'); | ||
|
|
||
| ### Create | ||
|
|
||
| To create a folder, use the `create()` method: | ||
|
|
||
| $attributes = [ | ||
| 'ou_name' => 'Employees', | ||
| 'container' => [ | ||
| 'Users' | ||
| ] | ||
| ]; | ||
|
|
||
| ### Delete | ||
|
|
||
| To delete a distinguished name, use the `delete()` method: | ||
|
|
||
| $distinguishedName = 'OU=Accounting,OU=User Accounts,DC=corp,DC=acme,DC=com'; | ||
|
|
||
| $deleted = $ad->folder()->delete($distinguishedName); | ||
|
|
||
| You can easily delete a found folder like so: | ||
|
|
||
| $folder = $ad->folder()->find('Accounting'); | ||
|
|
||
| if(is_array($folder) && array_key_exists('dn', $folder)) { | ||
|
|
||
| $ad->folder()->delete($folder['dn']); | ||
|
|
||
| } |
| @@ -0,0 +1,122 @@ | ||
| ## Getting Started | ||
|
|
||
| ### Basic Functionality | ||
|
|
||
| To connect to your Active Directory server, you'll have to provide a configuration array to a new Adldap instance. | ||
|
|
||
| This can be done like so: | ||
|
|
||
| use Adldap\Adldap; | ||
|
|
||
| $configuration = array( | ||
| 'user_id_key' => 'samaccountname', | ||
| 'account_suffix' => '@domain.local', | ||
| 'person_filter' => array('category' => 'objectCategory', 'person' => 'person'), | ||
| 'base_dn' => 'DC=domain,DC=local', | ||
| 'domain_controllers' => array('DC1.domain.local', 'DC2.domain.local'), | ||
| 'admin_username' => 'administrator', | ||
| 'admin_password' => 'password', | ||
| 'real_primarygroup' => true, | ||
| 'use_ssl' => false, | ||
| 'use_tls' => false, | ||
| 'recursive_groups' => true, | ||
| 'ad_port' => '389', | ||
| 'sso' => false, | ||
| ); | ||
|
|
||
| try | ||
| { | ||
| $ad = new Adldap($configuration); | ||
|
|
||
| echo "Awesome, we're connected!"; | ||
| } catch(AdldapException $e) | ||
| { | ||
| echo "Uh oh, looks like we had an issue trying to connect: $e"; | ||
| } | ||
|
|
||
| If you'd like to know what each configuration option means, please look at the [configuration page](CONFIGURATION.md). | ||
|
|
||
| When creating a new Adldap instance, it will automatically try and connect to your server, however this behavior | ||
| is completely configurable, and you can supply your own connection class to run LDAP queries off of if you wish. | ||
| See [Advanced Usage](#advanced-usage). | ||
|
|
||
| #### Authentication | ||
|
|
||
| Authenticating a user is easy, just call the `authenticate()` method like so: | ||
|
|
||
| $authenticated = $ad->authenticate('johndoe', 'password'); | ||
|
|
||
| echo $authenticated; // Returns true | ||
|
|
||
| However, if you'd like to stay authenticated as this user, you'll have to pass in `true` as the third parameter like so: | ||
|
|
||
| $preventRebind = true; | ||
|
|
||
| $authenticated = $ad->authenticate('johndoe', 'password', $preventRebind); | ||
|
|
||
| Now, when you call methods on the Adldap object, you're authenticated as John Doe, instead of the administrator. | ||
|
|
||
| #### Retrieving the last message / error from LDAP: | ||
|
|
||
| To retrieve the last message or error from LDAP, call the `getLastError()` method like so: | ||
|
|
||
| echo $ad->getLastError(); | ||
|
|
||
| ### Advanced Usage | ||
|
|
||
| #### Using a different LDAP Connection | ||
|
|
||
| If you'd like to supply your own LDAP connection class, supply your own by inserting it into the second parameter in | ||
| the Adldap constructor. The custom class will need to implement the `Adldap\Interfaces\ConnectionInterface` OR extend | ||
| the main Connection class (`Adldap\Connections\Ldap`). | ||
|
|
||
| use Adldap\Connections\Ldap; | ||
|
|
||
| class CustomLdapConnection extends Ldap | ||
| { | ||
| public function connect($hostname, $port = '389') | ||
| { | ||
| // Connect to LDAP my own way | ||
| } | ||
| } | ||
|
|
||
| Then using your new class: | ||
|
|
||
| $connection = new CustomLdapConnection; | ||
|
|
||
| $ad = new Adldap($configuration, $connection); | ||
|
|
||
| #### Disabling auto-connect on construct | ||
|
|
||
| By default, when Adldap is constructed, it automatically tries to connect to your server, though you can disable this | ||
| by passing in `false` in the last construct parameter. You will have to manually call the connect method by doing this. | ||
|
|
||
| $ad = new Adldap($configuration, null, false); | ||
|
|
||
| $ad->connect(); | ||
|
|
||
| #### Showing LDAP Warning / Errors | ||
|
|
||
| By default, LDAP warnings and errors are suppressed in favor of catchable exceptions thrown by Adldap. To display | ||
| warnings and errors, use the `showErrors()` method on the connection: | ||
|
|
||
| $ad->getLdapConnection()->showErrors(); | ||
|
|
||
| // Now all Adldap methods will display LDAP warnings / errors if they are thrown | ||
| $ad->user()->all(); | ||
|
|
||
| #### Overriding Adldap Classes and Methods | ||
|
|
||
| To override classes / methods, simply create a class that extends Adldap, and override them: | ||
|
|
||
| use Adldap\Adldap; | ||
|
|
||
| class MyAdldap extends Adldap { | ||
|
|
||
| // Overriding the user function to return your own User class | ||
| public function user() | ||
| { | ||
| return new MyUserClass(); | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,24 @@ | ||
| ## Group Functions | ||
|
|
||
| ### Get Primary Group | ||
|
|
||
| To retrieve a users primary group (due to LDAP not returning the distinguished name of their primary group), use the | ||
| `getPrimaryGroup()` method: | ||
|
|
||
| // Get the users information | ||
| $user = $ad->user()->find('John Doe'); | ||
|
|
||
| // Get their primary group ID | ||
| $primaryGroupId = $user['primarygroupid']; | ||
|
|
||
| // Get their object SID | ||
| $objectSid = $user['objectsid']; | ||
|
|
||
| /* | ||
| * Get the primary groups DN by | ||
| * passing in the users primary group ID | ||
| * and SID | ||
| */ | ||
| $groupDn = $ad->group()->getPrimaryGroup($primaryGroupId, $objectSid); | ||
|
|
||
| echo $groupDn; // Returns 'CN=Domain Users,CN=Users,DC=corp,DC=acme,DC=org' |
| @@ -0,0 +1,265 @@ | ||
| ## Searching Functions | ||
|
|
||
| The new Adldap Search functionality makes it really easy to query your AD server for exactly what you want. Let's get started. | ||
|
|
||
| To open a new search query, call the `search()` function on your AD object like so: | ||
|
|
||
| $ad = new Adldap($configuration); | ||
|
|
||
| $ad->search(); | ||
|
|
||
| #### All | ||
|
|
||
| To retrieve all entries in your AD, use the all function: | ||
|
|
||
| $results = $ad->search()->all(); | ||
|
|
||
| This will retrieve all entries from LDAP. However, be careful. AD has a limit of 1000 records per query (depending on your AD | ||
| server configuration of course), if your AD has more records than this, you will only see the 1000 records AD has | ||
| retrieved. LDAP will throw the following warning if this occurs: | ||
|
|
||
| Warning: ldap_search(): Partial search results returned: Sizelimit exceeded | ||
|
|
||
| However, LDAP functions are suppressed by default, so you won't see this message. If you'd like to show errors and warnings, call the `showErrors()` method | ||
| on the AD connection before performing the search like so: | ||
|
|
||
| $ad->getLdapConnection()->showErrors(); | ||
|
|
||
| $results = $ad->search()->all(); | ||
|
|
||
| #### Where | ||
|
|
||
| To perform a where clause on the search object, use the `where()` function: | ||
|
|
||
| $results = $ad->search()->where('cn', '=', 'John Doe')->get(); | ||
|
|
||
| This query would look for an object with the common name of 'John Doe' and return the results. | ||
|
|
||
| We could also perform a search for all objects beginning with the common name of 'John' using the `starts_with` operator: | ||
|
|
||
| $results = $ad->search()->where('cn', 'starts_with', 'John')->get(); | ||
|
|
||
| We can also search for all objects that end with the common name of `Doe` using the `ends_with` operator: | ||
|
|
||
| $results = $ad->search()->where('cn', 'ends_with', 'Doe')->get(); | ||
|
|
||
| We can also search for all objects with a common name that contains `John Doe` using the `contains` operator: | ||
|
|
||
| $results = $ad->search()->where('cn', 'contains', 'John Doe')->get(); | ||
|
|
||
| Or we can retrieve all objects that contain a common name attribute using the wildcard operator (`*`): | ||
|
|
||
| $results = $ad->search()->where('cn', '*')->get(); | ||
|
|
||
| This type of filter syntax allows you to clearly see what your searching for. | ||
|
|
||
| Remember, fields are case insensitive, so it doesn't matter if you use `->where('CN', '*')` or `->where('cn', '*')`, | ||
| they would return the same result. | ||
|
|
||
| It's also good to know that all values inserted into a where, or an orWhere method, | ||
| <b>are escaped</b> by default into a hex string, so you don't need to worry about escaping them. For example: | ||
|
|
||
| $query = $ad->search()->where('cn', '=', 'test//un-escaping//')->getQuery(); | ||
|
|
||
| // Returns '(cn=\74\65\73\74\2f\2f\75\6e\2d\65\73\63\61\70\69\6e\67\2f\2f)' | ||
|
|
||
| #### Or Where | ||
|
|
||
| To perform an 'or where' clause on the search object, use the `orWhere()` function. However, please be aware this | ||
| function performs differently than it would on a database. For example: | ||
|
|
||
| $results = $ad->search() | ||
| ->where('cn', '=', 'John Doe') | ||
| ->orWhere('cn' '=', 'Suzy Doe') | ||
| ->get(); | ||
|
|
||
| This query would return no results, because we're already defining that the common name (`cn`) must equal `John Doe`. Applying | ||
| the `orWhere()` does not amount to 'Look for an object with the common name as "John Doe" OR "Suzy Doe"'. This query would | ||
| actually amount to 'Look for an object with the common name that <b>equals</b> "John Doe" OR "Suzy Doe" | ||
|
|
||
| To solve the above problem, we would use `orWhere()` for both fields. For example: | ||
|
|
||
| $results = $ad->search() | ||
| ->orWhere('cn', '=', 'John Doe') | ||
| ->orWhere('cn' '=', 'Suzy Doe') | ||
| ->get(); | ||
|
|
||
| Now, we'll retrieve both John and Suzy's AD records, because the common name can equal either. | ||
|
|
||
| For another example, what if we wanted to retrieve | ||
|
|
||
| #### Select | ||
|
|
||
| If you'd like to include only certain fields in your search results, supply a string or an array to the `select()` method | ||
| like so: | ||
|
|
||
| // Selecting one field | ||
| $results = $ad->search()->select('cn')->all(); | ||
|
|
||
| // Selecting multiple fields | ||
| $results = $ad->search()->select(array('cn', 'displayname'))->all(); | ||
|
|
||
| All searches will return *all* information for each entry. Be sure to use `select($fields = array())` when you only | ||
| need a small amount of information. | ||
|
|
||
| #### Sort By | ||
|
|
||
| If you'd like to sort your returned results, call the `sortBy()` method like so: | ||
|
|
||
| // Returned results will be sorted by the common name in a descending order | ||
| $results = $ad->search()->where('cn', '=', 'John*')->sortBy('cn', 'desc')->get(); | ||
|
|
||
| The function is case insensitive with directions, so don't worry if you use `DESC` or `desc`. | ||
|
|
||
| #### Query | ||
|
|
||
| To perform a raw LDAP query yourself, use the `query()` method: | ||
|
|
||
| $results = $ad->search()->query('(cn=John Doe)'); | ||
|
|
||
| However, keep in mind the inserted query is not escaped. If you need to escape your values before the query, be sure | ||
| to do so using: | ||
|
|
||
| $escapedValue = $ad->getLdapConnection()->escape('John Doe'); | ||
|
|
||
| Then you can perform the above query like so: | ||
|
|
||
| $results = $ad->search()->query("(cn=$escapedValue)"); | ||
|
|
||
| #### Paginate | ||
|
|
||
| Pagination is useful when you have a limit on the returned results from LDAP. Using pagination, you will successfully be able | ||
| to view all LDAP results. To paginate your results, call the `paginate()` method: | ||
|
|
||
| $perPage = 25; | ||
|
|
||
| $currentPage = $_GET['page']; | ||
|
|
||
| $results = $ad->search()->where('objectClass', '=', 'person')->paginate($perPage, $currentPage); | ||
|
|
||
| <b>It's also good to know, that the current page starts at zero (zero being the first page).</b> If you'd like to present pages | ||
| differently, feel free to do so. | ||
|
|
||
| Paginating a search result will return a `Adldap\Objects\Paginator` instance. This object provides some handy functions: | ||
|
|
||
| $results = $ad->search()->where('objectClass', '=', 'person')->paginate($perPage, $currentPage); | ||
|
|
||
| $results->getPages(); // Returns total number of pages, int | ||
|
|
||
| $results->getCurrentPage(); // Returns current page number, int | ||
|
|
||
| $results->getPerPage(); // Returns the amount of entries allowed per page, int | ||
|
|
||
| $results->count(); // Returns the total amount of retrieved entries, int | ||
|
|
||
| // Iterate over the results like normal | ||
|
|
||
| foreach($results as $result) | ||
| { | ||
| echo $result['cn']; | ||
| } | ||
|
|
||
| #### Recursive | ||
|
|
||
| By default, all searches performed are recursive. If you'd like to disable recursive search, use the `recursive()` method: | ||
|
|
||
| $result = $ad->search()->recursive(false)->all(); | ||
|
|
||
| This would perform an `ldap_listing()` instead of an `ldap_search()`. | ||
|
|
||
| #### Read | ||
|
|
||
| If you'd like to perform a read instead of a listing or a recursive search, use the `read()` method: | ||
|
|
||
| $result = $ad->search()->read(true)->where('objectClass', '*')->get(); | ||
|
|
||
| This would perform an `ldap_read()` instead of an `ldap_listing()` or an `ldap_search()`. | ||
|
|
||
| #### Get Query | ||
|
|
||
| If you'd like to retrieve the current query to save or run it at another time, use the `getQuery()` method: | ||
|
|
||
| $query = $ad->search()->where('cn', '=', 'John Doe')->getQuery(); | ||
|
|
||
| echo $query; // Returns '(cn=\4a\6f\68\6e\20\44\6f\65)' | ||
|
|
||
| #### Get Wheres | ||
|
|
||
| If you'd like to retrieve the current wheres on the search object, call the `getWheres()` method: | ||
|
|
||
| $wheres = $ad->search()->where('cn', '=', 'John')->getWheres(); | ||
|
|
||
| var_dump($wheres); | ||
|
|
||
| #### Get Or Wheres | ||
|
|
||
| If you'd like to retrieve the current or wheres on the search object, call the `getOrWheres()` method: | ||
|
|
||
| $orWheres = $ad->search()->orWhere('cn', '=', 'John')->getOrWheres(); | ||
|
|
||
| var_dump($orWheres); | ||
|
|
||
| #### Get Selects | ||
|
|
||
| To retrieve the current selected fields in on the search object, use the `getSelects()` method: | ||
|
|
||
| $selects = $ad->search()->select(array('cn', 'dn'))->getSelects(); | ||
|
|
||
| var_dump($selects); | ||
|
|
||
| #### Has Selects | ||
|
|
||
| If you need to know if the search object currently contains selected fields, use the `hasSelects()` function: | ||
|
|
||
| echo $ad->search()->select('cn')->hasSelects(); // Returns true | ||
|
|
||
| ### Examples | ||
|
|
||
| #### User Examples | ||
|
|
||
| Retrieving all users who <b>do not</b> have the common name of 'John': | ||
|
|
||
| $results = $ad->search() | ||
| ->where('objectClass', '=', $ad->getUserIdKey()) | ||
| ->where('cn', '!', 'John') | ||
| ->get(); | ||
|
|
||
| Retrieving all users who do not have the common name of 'John' or 'Suzy': | ||
|
|
||
| $results = $ad->search() | ||
| ->where('objectClass', '=', $ad->getUserIdKey()) | ||
| ->orWhere('cn', '!', 'John') | ||
| ->orWhere('cn', '!', 'Suzy') | ||
| ->get(); | ||
|
|
||
| Retrieving all users who have a mail account: | ||
|
|
||
| $results = $ad->search() | ||
| ->where('objectClass', '=', $ad->getUserIdKey()) | ||
| ->where('mail', '*') | ||
| ->get(); | ||
|
|
||
| #### Computer Examples | ||
|
|
||
| Retrieving a all computers: | ||
|
|
||
| $results = $ad->search() | ||
| ->where('objectClass', '=', 'computer') | ||
| ->get(); | ||
|
|
||
| Retrieving all computers that run Windows 7: | ||
|
|
||
| $results = $ad->search() | ||
| ->where('objectClass', '=', 'computer') | ||
| ->where('operatingSystem', 'starts_with', 'Windows 7') | ||
| ->get(); | ||
|
|
||
| #### Folder (OU) examples | ||
|
|
||
| Retrieving a folder: | ||
|
|
||
| $folderName = 'Accounting'; | ||
|
|
||
| $results = $this->adldap->search() | ||
| ->where('OU', '=', $folderName) | ||
| ->first(); |
| @@ -0,0 +1,37 @@ | ||
| ## Upgrading to 5.0.0 | ||
|
|
||
| Breaking changes: | ||
|
|
||
| - Requires have been removed from all classes, and if using without an auto-loader (such as composer) you must require all | ||
| necessary files yourself | ||
| - `adLDAP\adLDAPException` now has a new namespace: `adLDAP\Exceptions\adLDAPException` | ||
| - `$adldap->user()->modify()` now throws an `adLDAPException` when the username parameter is null | ||
| - Inserting null/empty values into the username and/or password inside the `authenticate($username, $password)` function will now | ||
| result in an `adLDAPException`, instead of returning false | ||
| - Inserting null into the group name parameter inside the method `$adLDAP->group()->info($groupName)` now throws an adLDAP exception | ||
| instead of returning false | ||
| - Inserting null into the username parameter inside the method `$adLDAP->user()->info($username)` now throws an adLDAP exception | ||
| instead of returning false | ||
| - If LDAP is not bound when running query methods (such as `$adLDAP->search()`) then an `adLDAPException` will be thrown instead | ||
| of previously returning false. | ||
| - `pingController()` method removed | ||
|
|
||
|
|
||
| The arguments for finding a user has been changed from: | ||
|
|
||
| $adldap->user()->find($includeDescription = false, $searchField = false, $searchFilter = false, $sorted = true) | ||
|
|
||
| To: | ||
|
|
||
| $adldap->user()->find($includeDescription = false, $searchArray = array(), $sorted = true)) | ||
|
|
||
| This allows you to search for multiple parameters when looking for a user. [Thanks To](https://github.com/adldap/adLDAP/pull/17) | ||
|
|
||
|
|
||
| $adldap->group()->search($sAMAaccountType = Adldap::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription = false, $search = "*", $sorted = true); | ||
|
|
||
| Has Changed to: | ||
|
|
||
| $adldap->group()->search($sAMAaccountType = Adldap::ADLDAP_SECURITY_GLOBAL_GROUP, $select = array(), $sorted = true); | ||
|
|
||
| Removed function $adldap->group()->cn(); |
| @@ -0,0 +1,96 @@ | ||
| ## User Functions | ||
|
|
||
| ### All | ||
|
|
||
| To retrieve all users on AD, use the `all()` method: | ||
|
|
||
| $users = $ad->user()->all(); | ||
|
|
||
| ### Find | ||
|
|
||
| To retrieve all information on a user, use `find()` method: | ||
|
|
||
| $username = 'jdoe'; | ||
|
|
||
| $user = $ad->user()->find($username); | ||
|
|
||
| If you're only interested in certain LDAP fields, insert your fields in the second parameter: | ||
|
|
||
| $username = 'jdoe'; | ||
|
|
||
| $fields = [ | ||
| 'cn', | ||
| 'memberof' | ||
| ]; | ||
|
|
||
| $user = $ad->user()->find($username, $fields); | ||
|
|
||
| echo $user['cn']; | ||
| echo $user['memberof']; | ||
|
|
||
| ### Info | ||
|
|
||
| The `info()` method is an alias for the `find()` method, this exists for backwards compatibility. | ||
|
|
||
| $username = 'jdoe'; | ||
|
|
||
| $user = $ad->user()->info($username); | ||
|
|
||
| ### DN | ||
|
|
||
| To retrieve a users full distinguished name, use the `dn()` method: | ||
|
|
||
| $username = 'jdoe'; | ||
|
|
||
| $dn = $ad->user()->dn($username); | ||
|
|
||
| ### Create | ||
|
|
||
| ### Modify | ||
|
|
||
| ### Delete | ||
|
|
||
| To delete a user, use the `delete()` method: | ||
|
|
||
| $username = 'jdoe'; | ||
|
|
||
| $deleted = $ad->user()->delete($username); | ||
|
|
||
| ### Change Password | ||
|
|
||
| To change a users password, use the `changePassword()` method: | ||
|
|
||
| try | ||
| { | ||
| $newPassword = 'newpassword123'; | ||
|
|
||
| $oldPassword = 'oldpassword123'; | ||
|
|
||
| $changed = $ad->user()->changePassword('jdoe', $newPassword, $oldPassword); | ||
|
|
||
| } catch(Adldap\Exceptions\WrongPasswordException $e) | ||
| { | ||
| return "Uh oh, you've entered the wrong old password!"; | ||
| } catch(Adldap\Exceptions\PasswordPolicyException $e) | ||
| { | ||
| return "Looks like your new password doesn't meet our requirements. Try again." | ||
| } | ||
|
|
||
| ### Password Expiry | ||
|
|
||
| To retrieve a users password expiry date, use the `passwordExpiry()` method: | ||
|
|
||
| $results = $ad->user()->passwordExpiry('jdoe'); // Returns array|bool | ||
|
|
||
| $results['expires']; // Returns true / false if the users password expires | ||
| $results['has_expired']; // Returns true / false if the users password **has** expired | ||
| $results['expiry_timestamp']; // Returns the users password expiry date in unix time | ||
| $results['expiry_formatted']; // Returns the users password expiry date in a formatted string ('YYYY-MM-DD HH:MM:SS') | ||
|
|
||
| ### Get Last Logon | ||
|
|
||
| To retrieve a users last login time, use the `getLastLogon()` method: | ||
|
|
||
| $time = $ad->user()->getLastLogon('jdoe'); // Returns in Unix time | ||
|
|
||
| $date = date('Y-m-d h:i:s', $time); |
| @@ -0,0 +1,139 @@ | ||
| <?php | ||
|
|
||
| use adLDAP\adLDAP; | ||
|
|
||
| /* | ||
| Examples file | ||
| To test any of the functions, just change the 0 to a 1. | ||
| */ | ||
|
|
||
| //error_reporting(E_ALL ^ E_NOTICE); | ||
|
|
||
| include dirname(__FILE__).'/../lib/adLDAP/adLDAP.php'; | ||
|
|
||
| try { | ||
| $adldap = new adLDAP($options); | ||
| } catch (adLDAPException $e) { | ||
| echo $e; | ||
| exit(); | ||
| } | ||
| //var_dump($ldap); | ||
|
|
||
| echo("<pre>\n"); | ||
|
|
||
| // authenticate a username/password | ||
| if (0) { | ||
| $result = $adldap->authenticate('username', 'password'); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // add a group to a group | ||
| if (0) { | ||
| $result = $adldap->group()->addGroup('Parent Group Name', 'Child Group Name'); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // add a user to a group | ||
| if (0) { | ||
| $result = $adldap->group()->addUser('Group Name', 'username'); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // create a group | ||
| if (0) { | ||
| $attributes = array( | ||
| 'group_name' => 'Test Group', | ||
| 'description' => 'Just Testing', | ||
| 'container' => array('Groups','A Container'), | ||
| ); | ||
| $result = $adldap->group()->create($attributes); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // retrieve information about a group | ||
| if (0) { | ||
| // Raw data array returned | ||
| $result = $adldap->group()->info('Group Name'); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // create a user account | ||
| if (0) { | ||
| $attributes = array( | ||
| 'username' => 'freds', | ||
| 'logon_name' => 'freds@mydomain.local', | ||
| 'firstname' => 'Fred', | ||
| 'surname' => 'Smith', | ||
| 'company' => 'My Company', | ||
| 'department' => 'My Department', | ||
| 'email' => 'freds@mydomain.local', | ||
| 'container' => array('Container Parent','Container Child'), | ||
| 'enabled' => 1, | ||
| 'password' => 'Password123', | ||
| ); | ||
|
|
||
| try { | ||
| $result = $adldap->user()->create($attributes); | ||
| var_dump($result); | ||
| } catch (adLDAPException $e) { | ||
| echo $e; | ||
| exit(); | ||
| } | ||
| } | ||
|
|
||
| // retrieve the group membership for a user | ||
| if (0) { | ||
| $result = $adldap->user()->groups('username'); | ||
| print_r($result); | ||
| } | ||
|
|
||
| // retrieve information about a user | ||
| if (0) { | ||
| // Raw data array returned | ||
| $result = $adldap->user()->info('username'); | ||
| print_r($result); | ||
| } | ||
|
|
||
| // check if a user is a member of a group | ||
| if (0) { | ||
| $result = $adldap->user()->inGroup('username', 'Group Name'); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // modify a user account (this example will set "user must change password at next logon") | ||
| if (0) { | ||
| $attributes = array( | ||
| 'change_password' => 1, | ||
| ); | ||
| $result = $adldap->user()->modify('username', $attributes); | ||
| var_dump($result); | ||
| } | ||
|
|
||
| // change the password of a user. It must meet your domain's password policy | ||
| if (0) { | ||
| try { | ||
| $result = $adldap->user()->password('username', 'Password123'); | ||
| var_dump($result); | ||
| } catch (adLDAPException $e) { | ||
| echo $e; | ||
| exit(); | ||
| } | ||
| } | ||
|
|
||
| // see a user's last logon time | ||
| if (0) { | ||
| try { | ||
| $result = $adldap->user()->getLastLogon('username'); | ||
| var_dump(date('Y-m-d H:i:s', $result)); | ||
| } catch (adLDAPException $e) { | ||
| echo $e; | ||
| exit(); | ||
| } | ||
| } | ||
|
|
||
| // list the contents of the Users OU | ||
| if (0) { | ||
| $result = $adldap->folder()->listing(array('Users'), adLDAP::ADLDAP_FOLDER, false); | ||
| var_dump($result); | ||
| } |
| @@ -0,0 +1,22 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| Test for the new user collections object | ||
| */ | ||
|
|
||
| //error_reporting(E_ALL ^ E_NOTICE); | ||
|
|
||
| include dirname(__FILE__).'/../lib/adLDAP/adLDAP.php'; | ||
| try { | ||
| $adldap = new adLDAP($options); | ||
| } catch (adLDAPException $e) { | ||
| echo $e; | ||
| exit(); | ||
| } | ||
|
|
||
| echo("<pre>\n"); | ||
|
|
||
| $collection = $adldap->group()->infoCollection('groupname'); | ||
|
|
||
| print_r($collection->member); | ||
| print_r($collection->description); |
| @@ -0,0 +1,71 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * This file contains a working example of adLDAP in operation. | ||
| * | ||
| * @file | ||
| */ | ||
| if (!file_exists(__DIR__.'/../vendor/autoload.php')) { | ||
| echo 'Before using this demo, please run <code>composer dump-autoload</code>'; | ||
| exit(1); | ||
| } | ||
| require_once __DIR__.'/../vendor/autoload.php'; | ||
|
|
||
| use adLDAP\adLDAP; | ||
| use adLDAP\Exceptions\adLDAPException; | ||
|
|
||
| // Set up all options. | ||
| $options = [ | ||
| 'account_suffix' => '', | ||
| 'base_dn' => null, | ||
| 'domain_controllers' => [''], | ||
| 'admin_username' => null, | ||
| 'admin_password' => null, | ||
| 'real_primarygroup' => '', | ||
| 'use_ssl' => false, | ||
| 'use_tls' => false, | ||
| 'recursive_groups' => true, | ||
| 'ad_port' => adLDAP::ADLDAP_LDAP_PORT, | ||
| 'sso' => '', | ||
| ]; | ||
| // Update options from $_POST. | ||
| foreach ($options as $optName => $defaultValue) { | ||
| if (isset($_POST[$optName])) { | ||
| $options[$optName] = $_POST[$optName]; | ||
| } | ||
| } | ||
| // Validate options. | ||
| $options['domain_controllers'] = array_filter($options['domain_controllers']); | ||
|
|
||
| // Try to bind. | ||
| $adldap = false; | ||
| $exception = false; | ||
| if (is_array($options['domain_controllers']) && !empty($options['domain_controllers'][0])) { | ||
| try { | ||
| $adldap = new adLDAP($options); | ||
| // To pass through to the form: | ||
| $options['base_dn'] = $adldap->getBaseDn(); | ||
| $options['ad_port'] = $adldap->getPort(); | ||
| } catch (adLDAPException $e) { | ||
| $exception = $e; | ||
| } | ||
| } | ||
|
|
||
| // Handle log in. | ||
| $username = (!empty($_POST['username'])) ? $_POST['username'] : ''; | ||
| $info = false; | ||
| if ($adldap && !empty($username)) { | ||
| $password = $_POST['password']; | ||
| try { | ||
| $adldap->authenticate($username, $password); | ||
| $info = $adldap->user()->info($username, ['*']); | ||
| if (isset($info[0])) { | ||
| $info = $info[0]; | ||
| } | ||
| } catch (\adLDAP\Exceptions\adLDAPException $e) { | ||
| $exception = $e; | ||
| } | ||
| } | ||
|
|
||
| // Hand everything over to the view for display. | ||
| require 'view.html.php'; |
| @@ -0,0 +1,22 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| Test for the new user collections object | ||
| */ | ||
|
|
||
| //error_reporting(E_ALL ^ E_NOTICE); | ||
|
|
||
| include dirname(__FILE__).'/../lib/adLDAP/adLDAP.php'; | ||
| try { | ||
| $adldap = new adLDAP($options); | ||
| } catch (adLDAPException $e) { | ||
| echo $e; | ||
| exit(); | ||
| } | ||
|
|
||
| echo("<pre>\n"); | ||
|
|
||
| $collection = $adldap->user()->infoCollection('username'); | ||
|
|
||
| print_r($collection->memberOf); | ||
| print_r($collection->displayName); |
| @@ -0,0 +1,198 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8"> | ||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
| <title>adLDAP example</title> | ||
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> | ||
| <!--[if lt IE 9]> | ||
| <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> | ||
| <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> | ||
| <![endif]--> | ||
| </head> | ||
| <body> | ||
| <div class="container"> | ||
| <h1><a href="index.php">adLDAP example</a></h1> | ||
|
|
||
| <?php if ($exception): ?> | ||
| <p class="alert alert-danger"><?php echo $exception->getMessage() ?></p> | ||
| <?php endif ?> | ||
|
|
||
| <form method="post" action="index.php" class="inline"> | ||
| <div class="row"> | ||
| <div class="col-md-6"> | ||
| <h2>Options</h2> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>account_suffix</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="text" name="account_suffix" value="<?php echo $options['account_suffix'] ?>" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>base_dn</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="text" name="base_dn" value="<?php echo $options['base_dn'] ?>" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>domain_controllers</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <?php foreach ($options['domain_controllers'] as $dc): ?> | ||
| <input type="text" name="domain_controllers[]" class="form-control" value="<?php echo $dc ?>" /> | ||
| <?php endforeach ?> | ||
| <input type="text" name="domain_controllers[]" class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>admin_username</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="text" name="admin_username" value="<?php echo $options['admin_username'] ?>" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>admin_password</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="password" name="admin_password" value="<?php echo $options['admin_password'] ?>" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>real_primarygroup</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="text" name="real_primarygroup" value="<?php echo $options['real_primarygroup'] ?>" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>use_ssl</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="checkbox" name="use_ssl" value="<?php echo $options['use_ssl'] ?>" | ||
| class="form-control" <?php if ($options['use_ssl']) { | ||
| echo 'checked'; | ||
| } ?> /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>use_tls</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="checkbox" name="use_tls" value="<?php echo $options['use_tls'] ?>" | ||
| class="form-control" <?php if ($options['use_tls']) { | ||
| echo 'checked'; | ||
| } ?> /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>recursive_groups</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="checkbox" name="recursive_groups" value="<?php echo $options['recursive_groups'] ?>" | ||
| class="form-control" <?php if ($options['recursive_groups']) { | ||
| echo 'checked'; | ||
| } ?> /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>ad_port</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="text" name="ad_port" value="<?php echo $options['ad_port'] ?>" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="inline"><code>sso</code></label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="checkbox" name="sso" value="<?php echo $options['sso'] ?>" | ||
| class="form-control" <?php if ($options['sso']) { | ||
| echo 'checked'; | ||
| } ?> /> | ||
| </div> | ||
| </div> | ||
|
|
||
| <h2>Log In</h2> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="" for="username">Username:</label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="text" name="username" value="<?php echo $username ?>" id="username" | ||
| class="form-control" /> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div class="col-md-4"> | ||
| <label class="" for="password">Password:</label> | ||
| </div> | ||
| <div class="col-md-8"> | ||
| <input type="password" name="password" id="password" class="form-control" /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
|
|
||
| <div class="col-md-6"> | ||
| <h2> | ||
| Info | ||
| <input type="submit" class="btn btn-primary" value="Get Info" /> | ||
| <a href="index.php" class="btn btn-default">Reset</a> | ||
| </h2> | ||
| <?php if (!$adldap): ?> | ||
| <p class="alert alert-info"> | ||
| Please enter at least a domain controller at left, | ||
| then hit 'Get Info' above. | ||
| </p> | ||
| <?php endif ?> | ||
| <?php if ($adldap && $adldap->getLdapBind()): ?> | ||
| <p class="alert alert-success"> | ||
| Bound successfully. | ||
| </p> | ||
| <?php endif ?> | ||
| <?php if ($info): ?> | ||
| <h3>User info:</h3> | ||
| <dl> | ||
| <?php foreach ($info as $key => $val): ?> | ||
| <?php if (!is_string($key)) { | ||
| continue; | ||
| } ?> | ||
| <dt><?php echo $key ?></dt> | ||
| <dd><?php var_dump($val) ?></dd> | ||
| <?php endforeach ?> | ||
| </dl> | ||
| <?php endif ?> | ||
| </div> | ||
|
|
||
| </div> | ||
| </form> | ||
|
|
||
|
|
||
| </div> | ||
|
|
||
|
|
||
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> | ||
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> | ||
| </body> | ||
| </html> |
| @@ -0,0 +1,18 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <phpunit backupGlobals="false" | ||
| backupStaticAttributes="false" | ||
| bootstrap="vendor/autoload.php" | ||
| colors="true" | ||
| convertErrorsToExceptions="true" | ||
| convertNoticesToExceptions="true" | ||
| convertWarningsToExceptions="true" | ||
| processIsolation="false" | ||
| stopOnFailure="false" | ||
| syntaxCheck="false" | ||
| > | ||
| <testsuites> | ||
| <testsuite name="adLDAP Test Suite"> | ||
| <directory suffix="Test.php">./tests/</directory> | ||
| </testsuite> | ||
| </testsuites> | ||
| </phpunit> |
| @@ -0,0 +1,53 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| use Adldap\Adldap; | ||
|
|
||
| /** | ||
| * The Base Adldap class. | ||
| * | ||
| * Class AdldapBase | ||
| */ | ||
| abstract class AbstractAdldapBase | ||
| { | ||
| /** | ||
| * The current Adldap connection via dependency injection. | ||
| * | ||
| * @var Adldap | ||
| */ | ||
| protected $adldap; | ||
|
|
||
| /** | ||
| * The current Adldap connection. | ||
| * | ||
| * @var \Adldap\Interfaces\ConnectionInterface | ||
| */ | ||
| protected $connection; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param Adldap $adldap | ||
| */ | ||
| public function __construct(Adldap $adldap) | ||
| { | ||
| $this->adldap = $adldap; | ||
|
|
||
| $connection = $adldap->getLdapConnection(); | ||
|
|
||
| if ($connection) { | ||
| $this->connection = $connection; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns the current Adldap instance. | ||
| * | ||
| * @return Adldap | ||
| */ | ||
| public function getAdldap() | ||
| { | ||
| return $this->adldap; | ||
| } | ||
| } |
| @@ -0,0 +1,182 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| /** | ||
| * The AdldapQueryable class. This class provides | ||
| * some standard methods to queryable classes that | ||
| * extend this class. | ||
| * | ||
| * A 'queryable' class means that any Class that extends | ||
| * this class must query and return information from | ||
| * LDAP based on it's object class property. | ||
| * | ||
| * Class AdldapQueryable | ||
| */ | ||
| abstract class AbstractAdldapQueryable extends AbstractAdldapBase | ||
| { | ||
| /** | ||
| * The LDAP objects class name. | ||
| * | ||
| * @var string | ||
| */ | ||
| public $objectClass = ''; | ||
|
|
||
| /** | ||
| * Returns all entries with the current object class. | ||
| * | ||
| * @param array $fields | ||
| * @param bool $sorted | ||
| * @param string $sortBy | ||
| * @param string $sortByDirection | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function all($fields = [], $sorted = true, $sortBy = 'cn', $sortByDirection = 'asc') | ||
| { | ||
| $search = $this->adldap->search() | ||
| ->select($fields) | ||
| ->where('objectClass', '=', $this->objectClass); | ||
|
|
||
| if ($sorted) { | ||
| $search->sortBy($sortBy, $sortByDirection); | ||
| } | ||
|
|
||
| return $search->get(); | ||
| } | ||
|
|
||
| /** | ||
| * Finds a single entry using the objects current class | ||
| * and the specified common name. If fields are specified, | ||
| * then only those fields are returned in the result array. | ||
| * | ||
| * @param string $name | ||
| * @param array $fields | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function find($name, $fields = []) | ||
| { | ||
| $results = $this->adldap->search() | ||
| ->select($fields) | ||
| ->where('objectClass', '=', $this->objectClass) | ||
| ->where('anr', '=', $name) | ||
| ->first(); | ||
|
|
||
| if (count($results) > 0) { | ||
| return $results; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the DN of the current object class. | ||
| * | ||
| * @param string $name | ||
| * | ||
| * @return string|bool | ||
| */ | ||
| public function dn($name) | ||
| { | ||
| $info = $this->find($name); | ||
|
|
||
| if (is_array($info) && array_key_exists('dn', $info)) { | ||
| return $info['dn']; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Delete a distinguished name from Active Directory. | ||
| * | ||
| * @param string $dn The distinguished name to delete | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function delete($dn) | ||
| { | ||
| $this->adldap->utilities()->validateNotNullOrEmpty('Distinguished Name [dn]', $dn); | ||
|
|
||
| return $this->connection->delete($dn); | ||
| } | ||
|
|
||
| /** | ||
| * Alias for the find() method. | ||
| * | ||
| * @param string $name The name of the computer | ||
| * @param array $fields Attributes to return | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function info($name, $fields = []) | ||
| { | ||
| return $this->find($name, $fields); | ||
| } | ||
|
|
||
| /** | ||
| * Returns true / false if the specified group exists | ||
| * on the found LDAP entry. | ||
| * | ||
| * @param string $name | ||
| * @param string $group | ||
| * @param null $recursive | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function inGroup($name, $group, $recursive = null) | ||
| { | ||
| if ($recursive === null) { | ||
| $recursive = $this->adldap->getRecursiveGroups(); | ||
| } | ||
|
|
||
| // Get a list of the groups | ||
| $groups = $this->groups($name, $recursive); | ||
|
|
||
| // Return true if the specified group is in the group list | ||
| if (is_array($groups) && in_array($group, $groups)) { | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Finds the LDAP entry with the specified name, and returns | ||
| * the groups that it is a member of. | ||
| * | ||
| * @param string $name | ||
| * @param null $recursive | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function groups($name, $recursive = null) | ||
| { | ||
| if ($recursive === null) { | ||
| $recursive = $this->adldap->getRecursiveGroups(); | ||
| } | ||
|
|
||
| $info = $this->find($name); | ||
|
|
||
| if (is_array($info) && array_key_exists('memberof', $info)) { | ||
| $groups = $this->adldap->utilities()->niceNames($info['memberof']); | ||
|
|
||
| if ($recursive === true) { | ||
| foreach ($groups as $id => $groupName) { | ||
| $extraGroups = $this->adldap->group()->recursiveGroups($groupName); | ||
|
|
||
| $groups = array_merge($groups, $extraGroups); | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| * We'll return a filtered array and | ||
| * make sure every entry is unique | ||
| */ | ||
| return array_unique($groups); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| } |
| @@ -0,0 +1,51 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| /** | ||
| * Ldap Computer Management. | ||
| * | ||
| * Class AdldapComputers | ||
| */ | ||
| class AdldapComputers extends AbstractAdldapQueryable | ||
| { | ||
| /** | ||
| * The computers object class name. | ||
| * | ||
| * @var string | ||
| */ | ||
| public $objectClass = 'computer'; | ||
|
|
||
| /** | ||
| * Get the groups a computer is in. | ||
| * | ||
| * @param string $computerName The name of the computer | ||
| * @param null $recursive Whether to check recursively | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function groups($computerName, $recursive = null) | ||
| { | ||
| if ($recursive === null) { | ||
| $recursive = $this->adldap->getRecursiveGroups(); | ||
| } | ||
|
|
||
| $info = $this->find($computerName); | ||
|
|
||
| if (is_array($info) && array_key_exists('memberof', $info)) { | ||
| $groups = $this->adldap->utilities()->niceNames($info['memberof']); | ||
|
|
||
| if ($recursive === true) { | ||
| foreach ($groups as $id => $groupName) { | ||
| $extraGroups = $this->adldap->group()->recursiveGroups($groupName); | ||
|
|
||
| $groups = array_merge($groups, $extraGroups); | ||
| } | ||
| } | ||
|
|
||
| return $groups; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| } |
| @@ -0,0 +1,108 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| use Adldap\Objects\Contact; | ||
|
|
||
| /** | ||
| * Ldap Contacts Management. | ||
| * | ||
| * Class AdldapContacts | ||
| */ | ||
| class AdldapContacts extends AbstractAdldapQueryable | ||
| { | ||
| /** | ||
| * The contacts object class name. | ||
| * | ||
| * @var string | ||
| */ | ||
| public $objectClass = 'contact'; | ||
|
|
||
| /** | ||
| * Create a contact. | ||
| * | ||
| * @param array $attributes The attributes to set to the contact | ||
| * | ||
| * @return bool|string | ||
| */ | ||
| public function create(array $attributes) | ||
| { | ||
| $contact = new Contact($attributes); | ||
|
|
||
| $contact->validateRequired(); | ||
|
|
||
| // Translate the schema | ||
| $add = $this->adldap->ldapSchema($attributes); | ||
|
|
||
| // Set the cn to the contacts display name | ||
| $add['cn'][0] = $contact->{'display_name'}; | ||
|
|
||
| $add['objectclass'][0] = 'top'; | ||
| $add['objectclass'][1] = 'person'; | ||
| $add['objectclass'][2] = 'organizationalPerson'; | ||
| $add['objectclass'][3] = 'contact'; | ||
|
|
||
| if (!$contact->hasAttribute('exchange_hidefromlists')) { | ||
| $add['msExchHideFromAddressLists'][0] = 'TRUE'; | ||
| } | ||
|
|
||
| // Determine the container | ||
| $attributes['container'] = array_reverse($attributes['container']); | ||
|
|
||
| $container = 'OU='.implode(',OU=', $attributes['container']); | ||
|
|
||
| $dn = 'CN='.$this->adldap->utilities()->escapeCharacters($add['cn'][0]).', '.$container.','.$this->adldap->getBaseDn(); | ||
|
|
||
| // Add the entry | ||
| return $this->connection->add($dn, $add); | ||
| } | ||
|
|
||
| /** | ||
| * Modify a contact. Note if you set the enabled | ||
| * attribute you must not specify any other attributes. | ||
| * | ||
| * @param string $contactName The contact to query | ||
| * @param array $attributes The attributes to modify | ||
| * | ||
| * @return bool|string | ||
| */ | ||
| public function modify($contactName, $attributes) | ||
| { | ||
| $contactDn = $this->dn($contactName); | ||
|
|
||
| if ($contactDn) { | ||
| // Translate the update to the LDAP schema | ||
| $mod = $this->adldap->ldapSchema($attributes); | ||
|
|
||
| // Check to see if this is an enabled status update | ||
| if (!$mod) { | ||
| return false; | ||
| } | ||
|
|
||
| // Do the update | ||
| return $this->connection->modify($contactDn, $mod); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Mail enable a contact. Allows email to be sent to them through Exchange. | ||
| * | ||
| * @param string $contactName The contacts name | ||
| * @param string $emailAddress The contacts email address | ||
| * @param null $mailNickname | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function contactMailEnable($contactName, $emailAddress, $mailNickname = null) | ||
| { | ||
| $contactDn = $this->dn($contactName); | ||
|
|
||
| if ($contactDn) { | ||
| return $this->adldap->exchange()->contactMailEnable($contactDn, $emailAddress, $mailNickname); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| } |
| @@ -0,0 +1,143 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| use Adldap\Objects\Folder; | ||
| use Adldap\Adldap; | ||
|
|
||
| /** | ||
| * Ldap Folder / OU management. | ||
| * | ||
| * Class AdldapFolders | ||
| */ | ||
| class AdldapFolders extends AbstractAdldapQueryable | ||
| { | ||
| /** | ||
| * Returns all entries with the current object class. | ||
| * | ||
| * @param array $fields | ||
| * @param bool $sorted | ||
| * @param string $sortBy | ||
| * @param string $sortByDirection | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function all($fields = [], $sorted = true, $sortBy = 'name', $sortByDirection = 'asc') | ||
| { | ||
| $search = $this->adldap->search() | ||
| ->select($fields) | ||
| ->where('objectClass', '*') | ||
| ->where('distinguishedname', '!', $this->adldap->getBaseDn()); | ||
|
|
||
| if ($sorted) { | ||
| $search->sortBy($sortBy, $sortByDirection); | ||
| } | ||
|
|
||
| return $search->get(); | ||
| } | ||
|
|
||
| /** | ||
| * Finds a single entry using the objects current class | ||
| * and the specified common name. | ||
| * | ||
| * @param string $name | ||
| * @param array $fields | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function find($name, $fields = []) | ||
| { | ||
| $results = $this->adldap->search() | ||
| ->select($fields) | ||
| ->where('OU', '=', $name) | ||
| ->first(); | ||
|
|
||
| if (count($results) > 0) { | ||
| return $results; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Returns a folder listing for a specific OU. | ||
| * See http://adldap.sourceforge.net/wiki/doku.php?id=api_folder_functions. | ||
| * | ||
| * If folderName is set to NULL this will list the root, strongly recommended | ||
| * to set $recursive to false in that instance! | ||
| * | ||
| * @param array $folders | ||
| * @param string $dnType | ||
| * @param null $recursive | ||
| * @param null $type | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function listing($folders = [], $dnType = Adldap::ADLDAP_FOLDER, $recursive = null, $type = null) | ||
| { | ||
| $search = $this->adldap->search(); | ||
|
|
||
| if (is_array($folders) && count($folders) > 0) { | ||
| /* | ||
| * Reverse the folder array so it's more | ||
| * akin to navigating a folder structure | ||
| */ | ||
| $folders = array_reverse($folders); | ||
|
|
||
| /* | ||
| * Get the combined OU string for the search. | ||
| * | ||
| * ex. OU=Users,OU=Acme | ||
| */ | ||
| $ou = $dnType.'='.implode(','.$dnType.'=', $folders); | ||
|
|
||
| $search->where('distinguishedname', '!', $ou.$this->adldap->getBaseDn()); | ||
|
|
||
| // Apply the OU to the base DN | ||
| $dn = $ou.','.$this->adldap->getBaseDn(); | ||
|
|
||
| $search->setDn($dn); | ||
| } else { | ||
| $search->where('distinguishedname', '!', $this->adldap->getBaseDn()); | ||
| } | ||
|
|
||
| if ($type === null) { | ||
| $search->where('objectClass', '*'); | ||
| } else { | ||
| $search->where('objectClass', '=', $type); | ||
| } | ||
|
|
||
| if ($recursive === false) { | ||
| $search->recursive(false); | ||
| } | ||
|
|
||
| return $search->get(); | ||
| } | ||
|
|
||
| /** | ||
| * Create an organizational unit. | ||
| * | ||
| * @param array $attributes Default attributes of the ou | ||
| * | ||
| * @return bool|string | ||
| */ | ||
| public function create(array $attributes) | ||
| { | ||
| $folder = new Folder($attributes); | ||
|
|
||
| $folder->validateRequired(); | ||
|
|
||
| $folder->setAttribute('container', array_reverse($folder->getAttribute('container'))); | ||
|
|
||
| $add = []; | ||
|
|
||
| $add['objectClass'] = 'organizationalUnit'; | ||
| $add['OU'] = $folder->getAttribute('ou_name'); | ||
|
|
||
| $containers = 'OU='.implode(',OU=', $folder->getAttribute('container')); | ||
|
|
||
| $dn = 'OU='.$add['OU'].', '.$containers.$this->adldap->getBaseDn(); | ||
|
|
||
| return $this->connection->add($dn, $add); | ||
| } | ||
| } |
| @@ -0,0 +1,373 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| use Adldap\Objects\Group; | ||
| use Adldap\Adldap; | ||
|
|
||
| /** | ||
| * Ldap Group management. | ||
| * | ||
| * Class AdldapGroups | ||
| */ | ||
| class AdldapGroups extends AbstractAdldapQueryable | ||
| { | ||
| /** | ||
| * The groups object category string. | ||
| * | ||
| * @var string | ||
| */ | ||
| public $objectCategory = 'group'; | ||
|
|
||
| /** | ||
| * The groups object class string. | ||
| * | ||
| * @var string | ||
| */ | ||
| public $objectClass = 'group'; | ||
|
|
||
| /** | ||
| * Returns a complete list of the groups in AD based on a SAM Account Type. | ||
| * | ||
| * @param int $sAMAaccountType The account type to return | ||
| * @param array $select The fields you want to retrieve for each | ||
| * @param bool $sorted Whether to sort the results | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function search($sAMAaccountType = Adldap::ADLDAP_SECURITY_GLOBAL_GROUP, $select = [], $sorted = true) | ||
| { | ||
| $search = $this->adldap->search() | ||
| ->select($select) | ||
| ->where('objectCategory', '=', 'group'); | ||
|
|
||
| if ($sAMAaccountType !== null) { | ||
| $search->where('samaccounttype', '=', $sAMAaccountType); | ||
| } | ||
|
|
||
| if ($sorted) { | ||
| $search->sortBy('samaccountname', 'asc'); | ||
| } | ||
|
|
||
| return $search->get(); | ||
| } | ||
|
|
||
| /** | ||
| * Add a group to a group. | ||
| * | ||
| * @param string $parent The parent group name | ||
| * @param string $child The child group name | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function addGroup($parent, $child) | ||
| { | ||
| // Find the parent group's dn | ||
| $parentDn = $this->dn($parent); | ||
|
|
||
| $childDn = $this->dn($child); | ||
|
|
||
| if ($parentDn && $childDn) { | ||
| $add['member'] = $childDn; | ||
|
|
||
| // Add the child to the parent group and return the result | ||
| return $this->connection->modAdd($parentDn, $add); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Add a user to a group. | ||
| * | ||
| * @param string $groupName The group to add the user to | ||
| * @param string $username The user to add to the group | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function addUser($groupName, $username) | ||
| { | ||
| $groupDn = $this->dn($groupName); | ||
|
|
||
| $userDn = $this->adldap->user()->dn($username); | ||
|
|
||
| if ($groupDn && $userDn) { | ||
| $add['member'] = $userDn; | ||
|
|
||
| return $this->connection->modAdd($groupDn, $add); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Add a contact to a group. | ||
| * | ||
| * @param string $groupName The group to add the contact to | ||
| * @param string $contactDn The DN of the contact to add | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function addContact($groupName, $contactDn) | ||
| { | ||
| $groupDn = $this->dn($groupName); | ||
|
|
||
| if ($groupDn && $contactDn) { | ||
| $add = []; | ||
| $add['member'] = $contactDn; | ||
|
|
||
| return $this->connection->modAdd($groupDn, $add); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Create a group. | ||
| * | ||
| * @param array $attributes Default attributes of the group | ||
| * | ||
| * @return bool|string | ||
| */ | ||
| public function create(array $attributes) | ||
| { | ||
| $group = new Group($attributes); | ||
|
|
||
| $group->validateRequired(); | ||
|
|
||
| // Reset the container by reversing the current container | ||
| $group->setAttribute('container', array_reverse($group->getAttribute('container'))); | ||
|
|
||
| $add['cn'] = $group->getAttribute('group_name'); | ||
| $add['samaccountname'] = $group->getAttribute('group_name'); | ||
| $add['objectClass'] = 'Group'; | ||
| $add['description'] = $group->getAttribute('description'); | ||
|
|
||
| $container = 'OU='.implode(',OU=', $group->getAttribute('container')); | ||
|
|
||
| $dn = 'CN='.$add['cn'].', '.$container.','.$this->adldap->getBaseDn(); | ||
|
|
||
| return $this->connection->add($dn, $add); | ||
| } | ||
|
|
||
| /** | ||
| * Rename a group. | ||
| * | ||
| * @param string $groupName The group to rename | ||
| * @param string $newName The new name to give the group | ||
| * @param array $container | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function rename($groupName, $newName, $container) | ||
| { | ||
| $groupDn = $this->dn($groupName); | ||
|
|
||
| if ($groupDn) { | ||
| $newRDN = 'CN='.$newName; | ||
|
|
||
| // Determine the container | ||
| $container = array_reverse($container); | ||
| $container = 'OU='.implode(', OU=', $container); | ||
|
|
||
| $dn = $container.', '.$this->adldap->getBaseDn(); | ||
|
|
||
| return $this->connection->rename($groupDn, $newRDN, $dn, true); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Remove a group from a group. | ||
| * | ||
| * @param string $parentName The parent group name | ||
| * @param string $childName The child group name | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function removeGroup($parentName, $childName) | ||
| { | ||
| $parentDn = $this->dn($parentName); | ||
|
|
||
| $childDn = $this->dn($childName); | ||
|
|
||
| if (is_string($parentDn) && is_string($childDn)) { | ||
| $del = []; | ||
| $del['member'] = $childDn; | ||
|
|
||
| return $this->connection->modDelete($parentDn, $del); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Remove a user from a group. | ||
| * | ||
| * @param string $groupName The group to remove a user from | ||
| * @param string $username The AD user to remove from the group | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function removeUser($groupName, $username) | ||
| { | ||
| $groupDn = $this->dn($groupName); | ||
|
|
||
| $userDn = $this->adldap->user()->dn($username); | ||
|
|
||
| if (is_string($groupDn) && is_string($userDn)) { | ||
| $del = []; | ||
| $del['member'] = $userDn; | ||
|
|
||
| return $this->connection->modDelete($groupDn, $del); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Remove a contact from a group. | ||
| * | ||
| * @param string $group The group to remove the contact from | ||
| * @param string $contactName The contact to remove | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function removeContact($group, $contactName) | ||
| { | ||
| // Find the parent dn | ||
| $groupDn = $this->dn($group); | ||
|
|
||
| $contactDn = $this->adldap->contact()->dn($contactName); | ||
|
|
||
| if (is_string($groupDn) && is_string($contactDn)) { | ||
| $del = []; | ||
| $del['member'] = $contactDn; | ||
|
|
||
| return $this->connection->modDelete($groupDn, $del); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Return a list of members in a group. | ||
| * | ||
| * @param string $group The group to query | ||
| * @param array $fields The fields to retrieve for each member | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function members($group, $fields = []) | ||
| { | ||
| $group = $this->find($group); | ||
|
|
||
| if (is_array($group) && array_key_exists('member', $group)) { | ||
| $members = []; | ||
|
|
||
| foreach ($group['member'] as $member) { | ||
| $members[] = $this->adldap->search() | ||
| ->setDn($member) | ||
| ->select($fields) | ||
| ->where('objectClass', '=', 'user') | ||
| ->where('objectClass', '=', 'person') | ||
| ->first(); | ||
| } | ||
|
|
||
| return $members; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Return a complete list of "groups in groups". | ||
| * | ||
| * @param string $groupName The group to get the list from | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function recursiveGroups($groupName) | ||
| { | ||
| $groups = []; | ||
|
|
||
| $info = $this->find($groupName); | ||
|
|
||
| if (is_array($info) && array_key_exists('cn', $info)) { | ||
| $groups[] = $info['cn']; | ||
|
|
||
| if (array_key_exists('memberof', $info)) { | ||
| if (is_array($info['memberof'])) { | ||
| foreach ($info['memberof'] as $group) { | ||
| $explodedDn = $this->connection->explodeDn($group); | ||
|
|
||
| $groups = array_merge($groups, $this->recursiveGroups($explodedDn[0])); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return $groups; | ||
| } | ||
|
|
||
| /** | ||
| * Returns a complete list of security groups in AD. | ||
| * | ||
| * @param bool $includeDescription Whether to return a description | ||
| * @param string $search Search parameters | ||
| * @param bool $sorted Whether to sort the results | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function allSecurity($includeDescription = false, $search = '*', $sorted = true) | ||
| { | ||
| return $this->search(Adldap::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription, $search, $sorted); | ||
| } | ||
|
|
||
| /** | ||
| * Returns a complete list of distribution lists in AD. | ||
| * | ||
| * @param bool $includeDescription Whether to return a description | ||
| * @param string $search Search parameters | ||
| * @param bool $sorted Whether to sort the results | ||
| * | ||
| * @return array|bool | ||
| */ | ||
| public function allDistribution($includeDescription = false, $search = '*', $sorted = true) | ||
| { | ||
| return $this->search(Adldap::ADLDAP_DISTRIBUTION_GROUP, $includeDescription, $search, $sorted); | ||
| } | ||
|
|
||
| /** | ||
| * Coping with AD not returning the primary group | ||
| * http://support.microsoft.com/?kbid=321360. | ||
| * | ||
| * This is a re-write based on code submitted by Bruce which prevents the | ||
| * need to search each security group to find the true primary group | ||
| * | ||
| * @param string $groupId Group ID | ||
| * @param string $userId User's Object SID | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function getPrimaryGroup($groupId, $userId) | ||
| { | ||
| $this->adldap->utilities()->validateNotNull('Group ID', $groupId); | ||
| $this->adldap->utilities()->validateNotNull('User ID', $userId); | ||
|
|
||
| $groupId = substr_replace($userId, pack('V', $groupId), strlen($userId) - 4, 4); | ||
|
|
||
| $sid = $this->adldap->utilities()->getTextSID($groupId); | ||
|
|
||
| $result = $this->adldap->search() | ||
| ->where('objectsid', '=', $sid) | ||
| ->first(); | ||
|
|
||
| if (is_array($result) && array_key_exists('dn', $result)) { | ||
| return $result['dn']; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| } |
| @@ -0,0 +1,355 @@ | ||
| <?php | ||
|
|
||
| namespace Adldap\Classes; | ||
|
|
||
| use Adldap\Exceptions\AdldapException; | ||
|
|
||
| /** | ||
| * AdLDAP Utility Functions. | ||
| * | ||
| * Class AdldapUtils | ||
| */ | ||
| class AdldapUtils extends AbstractAdldapBase | ||
| { | ||
| /** | ||
| * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN). | ||
| * | ||
| * @param array $groups | ||
| * | ||
| * @return array | ||
| */ | ||
| public function niceNames($groups) | ||
| { | ||
| $groupNames = []; | ||
|
|
||
| if (is_array($groups) && count($groups) > 0) { | ||
| foreach ($groups as $group) { | ||
| $explodedDn = $this->connection->explodeDn($group); | ||
|
|
||
| // Assuming the zero key is the CN | ||
| $groupNames[] = $explodedDn[0]; | ||
| } | ||
| } elseif (is_string($groups)) { | ||
| // If there's a single entry, groups will be a string | ||
| $explodedDn = $this->connection->explodeDn($groups); | ||
|
|
||
| $groupNames[] = $explodedDn[0]; | ||
| } | ||
|
|
||
| return $groupNames; | ||
| } | ||
|
|
||
| /** | ||
| * Escape characters for use in an ldap_create function. | ||
| * | ||
| * @param string $str | ||
| * | ||
| * @return string | ||
| */ | ||
| public function escapeCharacters($str) | ||
| { | ||
| return str_replace(',', "\,", $str); | ||
| } | ||
|
|
||
| /** | ||
| * Converts a string GUID to a hexdecimal value so it can be queried. | ||
| * | ||
| * @param string $strGUID A string representation of a GUID | ||
| * | ||
| * @return string | ||
| */ | ||
| public function strGuidToHex($strGUID) | ||
| { | ||
| $strGUID = str_replace('-', '', $strGUID); | ||
|
|
||
| $octet_str = '\\'.substr($strGUID, 6, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 4, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 2, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 0, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 10, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 8, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 14, 2); | ||
| $octet_str .= '\\'.substr($strGUID, 12, 2); | ||
|
|
||
| $length = (strlen($strGUID) - 2); | ||
|
|
||
| for ($i = 16; $i <= $length; $i++) { | ||
| if (($i % 2) == 0) { | ||
| $octet_str .= '\\'.substr($strGUID, $i, 2); | ||
| } | ||
| } | ||
|
|
||
| return $octet_str; | ||
| } | ||
|
|
||
| /** | ||
| * Convert a binary SID to a text SID. | ||
| * | ||
| * @param string $binsid A Binary SID | ||
| * | ||
| * @return string | ||
| */ | ||
| public function getTextSID($binsid) | ||
| { | ||
| $hex_sid = bin2hex($binsid); | ||
|
|
||
| $rev = hexdec(substr($hex_sid, 0, 2)); | ||
|
|
||
| $subcount = hexdec(substr($hex_sid, 2, 2)); | ||
|
|
||
| $auth = hexdec(substr($hex_sid, 4, 12)); | ||
|
|
||
| $result = "$rev-$auth"; | ||
|
|
||
| $subauth = []; | ||
|
|
||
| for ($x = 0;$x < $subcount; $x++) { | ||
| $subauth[$x] = hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8))); | ||
|
|
||
| $result .= '-'.$subauth[$x]; | ||
| } | ||
|
|
||
| // Cheat by tacking on the S- | ||
| return 'S-'.$result; | ||
| } | ||
|
|
||
| /** | ||
| * Converts a little-endian hex number to one that hexdec() can convert. | ||
| * | ||
| * @param string $hex A hex code | ||
| * | ||
| * @return string | ||
| */ | ||
| public function littleEndian($hex) | ||
| { | ||
| $result = ''; | ||
|
|
||
| for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) { | ||
| $result .= substr($hex, $x, 2); | ||
| } | ||
|
|
||
| return $result; | ||
| } | ||
|
|
||
| /** | ||
| * Converts a binary attribute to a string. | ||
| * | ||
| * @param string $bin A binary LDAP attribute | ||
| * | ||
| * @return string | ||
| */ | ||
| public function binaryToText($bin) | ||
| { | ||
| $hex_guid = bin2hex($bin); | ||
|
|
||
| $hex_guid_to_guid_str = ''; | ||
|
|
||
| for ($k = 1; $k <= 4; ++$k) { | ||
| $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2); | ||
| } | ||
|
|
||
| $hex_guid_to_guid_str .= '-'; | ||
|
|
||
| for ($k = 1; $k <= 2; ++$k) { | ||
| $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2); | ||
| } | ||
|
|
||
| $hex_guid_to_guid_str .= '-'; | ||
|
|
||
| for ($k = 1; $k <= 2; ++$k) { | ||
| $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2); | ||
| } | ||
|
|
||
| $hex_guid_to_guid_str .= '-'.substr($hex_guid, 16, 4); | ||
|
|
||
| $hex_guid_to_guid_str .= '-'.substr($hex_guid, 20); | ||
|
|
||
| return strtoupper($hex_guid_to_guid_str); | ||
| } | ||
|
|
||
| /** | ||
| * Converts a binary GUID to a string GUID. | ||
| * | ||
| * @param string $binaryGuid The binary GUID attribute to convert | ||
| * | ||
| * @return string | ||
| */ | ||
| public function decodeGuid($binaryGuid) | ||
| { | ||
| $this->validateNotNull('Binary GUID', $binaryGuid); | ||
|
|
||
| $strGUID = $this->binaryToText($binaryGuid); | ||
|
|
||
| return $strGUID; | ||
| } | ||
|
|
||
| /** | ||
| * Convert a boolean value to a string. | ||
| * You should never need to call this yourself. | ||
| * | ||
| * @param bool $bool Boolean value | ||
| * | ||
| * @return string | ||
| */ | ||
| public function boolToStr($bool) | ||
| { | ||
| return ($bool) ? 'TRUE' : 'FALSE'; | ||
| } | ||
|
|
||
| /** | ||
| * Convert 8bit characters e.g. accented characters to UTF8 encoded characters. | ||
| * | ||
| * @param $item | ||
| * @param $key | ||
| */ | ||
| public function encode8Bit(&$item, $key) | ||
| { | ||
| $encode = false; | ||
|
|
||
| if (is_string($item)) { | ||
| $length = strlen($item); | ||
|
|
||
| for ($i = 0; $i < $length; $i++) { | ||
| if (ord($item[$i]) >> 7) { | ||
| $encode = true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if ($encode === true && $key != 'password') { | ||
| $item = utf8_encode($item); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Round a Windows timestamp down to seconds and remove | ||
| * the seconds between 1601-01-01 and 1970-01-01. | ||
| * | ||
| * @param float $windowsTime | ||
| * | ||
| * @return float | ||
| */ | ||
| public static function convertWindowsTimeToUnixTime($windowsTime) | ||
| { | ||
| return round($windowsTime / 10000000) - 11644473600; | ||
| } | ||
|
|
||
| /** | ||
| * Convert DN string to array. | ||
| * | ||
| * @param $dnStr | ||
| * @param bool $excludeBaseDn exclude base DN from results | ||
| * | ||
| * @return array | ||
| */ | ||
| public function dnStrToArr($dnStr, $excludeBaseDn = true, $includeAttributes = false) | ||
| { | ||
| if ($excludeBaseDn) { | ||
| return ldap_explode_dn($dnStr, ($includeAttributes ? 0 : 1)); | ||
| } else { | ||
| return ldap_explode_dn($this->adldap->getBaseDn().$dnStr, ($includeAttributes ? 0 : 1)); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Validates if the function Bcmod exists. | ||
| * Throws an exception otherwise. | ||
| * | ||
| * @return bool | ||
| * | ||
| * @throws AdldapException | ||
| */ | ||
| public function validateBcmodExists() | ||
| { | ||
| if (!function_exists('bcmod')) { | ||
| $message = 'Missing function support [bcmod] http://php.net/manual/en/function.bcmod.php'; | ||
|
|
||
| throw new AdldapException($message); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Validates that the current LDAP connection is bound. This | ||
| * will throw an AdldapException otherwise. | ||
| * | ||
| * @return bool | ||
| * | ||
| * @throws AdldapException | ||
| */ | ||
| public function validateLdapIsBound() | ||
| { | ||
| if ($this->adldap->getLdapBind()) { | ||
| return true; | ||
| } | ||
|
|
||
| $message = 'No LDAP connection is currently bound.'; | ||
|
|
||
| throw new AdldapException($message); | ||
| } | ||
|
|
||
| /** | ||
| * Validates that the inserted value is not null or empty. This | ||
| * will throw an AdldapException otherwise. | ||
| * | ||
| * @param string $parameter | ||
| * @param string $value | ||
| * | ||
| * @return bool | ||
| * | ||
| * @throws AdldapException | ||
| */ | ||
| public function validateNotNullOrEmpty($parameter, $value) | ||
| { | ||
| $this->validateNotNull($parameter, $value); | ||
|
|
||
| $this->validateNotEmpty($parameter, $value); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Validates that the inserted value of the specified parameter | ||
| * is not null. This will throw an AdldapException otherwise. | ||
| * | ||
| * @param string $parameter | ||
| * @param mixed $value | ||
| * | ||
| * @return bool | ||
| * | ||
| * @throws AdldapException | ||
| */ | ||
| public function validateNotNull($parameter, $value) | ||
| { | ||
| if ($value !== null) { | ||
| return true; | ||
| } | ||
|
|
||
| $message = sprintf('Parameter: %s cannot be null.', $parameter); | ||
|
|
||
| throw new AdldapException($message); | ||
| } | ||
|
|
||
| /** | ||
| * Validates that the inserted value of the specified parameter | ||
| * is not empty. This will throw an AdldapException otherwise. | ||
| * | ||
| * @param string $parameter | ||
| * @param mixed $value | ||
| * | ||
| * @return bool | ||
| * | ||
| * @throws AdldapException | ||
| */ | ||
| public function validateNotEmpty($parameter, $value) | ||
| { | ||
| if (!empty($value)) { | ||
| return true; | ||
| } | ||
|
|
||
| $message = sprintf('Parameter: %s cannot be empty.', $parameter); | ||
|
|
||
| throw new AdldapException($message); | ||
| } | ||
| } |