| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- <?php
- /**
- * LDAP Authentication Class
- * Handles LDAP directory authentication and user information retrieval
- */
- class LDAPAuth {
- private $connection;
- private $config;
-
- public function __construct() {
- $this->config = [
- 'host' => LDAP_HOST,
- 'port' => LDAP_PORT,
- 'base_dn' => LDAP_BASE_DN,
- 'user_filter' => LDAP_USER_FILTER,
- 'bind_dn' => LDAP_BIND_DN,
- 'bind_password' => LDAP_BIND_PASSWORD,
- 'email_attribute' => LDAP_EMAIL_ATTRIBUTE,
- 'name_attribute' => LDAP_NAME_ATTRIBUTE
- ];
- }
-
- public function authenticate($username, $password) {
- try {
- // Connect to LDAP server
- $this->connect();
-
- // First bind with service account if configured
- if (!empty($this->config['bind_dn'])) {
- if (!ldap_bind($this->connection, $this->config['bind_dn'], $this->config['bind_password'])) {
- throw new Exception('LDAP bind failed with service account');
- }
- }
-
- // Search for user
- $filter = str_replace('{username}', ldap_escape($username, '', LDAP_ESCAPE_FILTER), $this->config['user_filter']);
- $search = ldap_search($this->connection, $this->config['base_dn'], $filter, [$this->config['email_attribute'], $this->config['name_attribute'], 'dn']);
-
- if (!$search) {
- throw new Exception('LDAP search failed');
- }
-
- $entries = ldap_get_entries($this->connection, $search);
-
- if ($entries['count'] === 0) {
- return false;
- }
-
- $user_dn = $entries[0]['dn'];
-
- // Try to bind with user credentials
- if (@ldap_bind($this->connection, $user_dn, $password)) {
- return true;
- }
-
- return false;
-
- } catch (Exception $e) {
- error_log('LDAP Authentication Error: ' . $e->getMessage());
- return false;
- } finally {
- $this->disconnect();
- }
- }
-
- public function getUserInfo($username) {
- try {
- $this->connect();
-
- // Bind with service account if configured
- if (!empty($this->config['bind_dn'])) {
- if (!ldap_bind($this->connection, $this->config['bind_dn'], $this->config['bind_password'])) {
- throw new Exception('LDAP bind failed with service account');
- }
- }
-
- // Search for user
- $filter = str_replace('{username}', ldap_escape($username, '', LDAP_ESCAPE_FILTER), $this->config['user_filter']);
- $search = ldap_search($this->connection, $this->config['base_dn'], $filter, [
- $this->config['email_attribute'],
- $this->config['name_attribute'],
- 'dn',
- 'cn',
- 'givenName',
- 'sn',
- 'mail',
- 'uid'
- ]);
-
- if (!$search) {
- throw new Exception('LDAP search failed');
- }
-
- $entries = ldap_get_entries($this->connection, $search);
-
- if ($entries['count'] === 0) {
- return null;
- }
-
- $user_entry = $entries[0];
-
- $userInfo = [
- 'ldap_dn' => $user_entry['dn'],
- 'username' => $username,
- 'email' => $this->getLdapAttribute($user_entry, $this->config['email_attribute']),
- 'name' => $this->getLdapAttribute($user_entry, $this->config['name_attribute']),
- 'first_name' => $this->getLdapAttribute($user_entry, 'givenName'),
- 'last_name' => $this->getLdapAttribute($user_entry, 'sn'),
- 'full_name' => $this->getLdapAttribute($user_entry, 'cn'),
- 'uid' => $this->getLdapAttribute($user_entry, 'uid')
- ];
-
- return $userInfo;
-
- } catch (Exception $e) {
- error_log('LDAP User Info Error: ' . $e->getMessage());
- return null;
- } finally {
- $this->disconnect();
- }
- }
-
- public function testConnection() {
- try {
- $this->connect();
-
- // Test bind
- if (!empty($this->config['bind_dn'])) {
- $bind_result = ldap_bind($this->connection, $this->config['bind_dn'], $this->config['bind_password']);
- } else {
- $bind_result = ldap_bind($this->connection);
- }
-
- if (!$bind_result) {
- throw new Exception('LDAP bind failed');
- }
-
- // Test search
- $search = ldap_search($this->connection, $this->config['base_dn'], '(objectClass=*)', ['dn']);
- if (!$search) {
- throw new Exception('LDAP search failed');
- }
-
- return true;
-
- } catch (Exception $e) {
- return false;
- } finally {
- $this->disconnect();
- }
- }
-
- private function connect() {
- $connection_string = $this->config['host'] . ':' . $this->config['port'];
-
- // Suppress LDAP warnings for cleaner error handling
- $this->connection = @ldap_connect($connection_string);
-
- if (!$this->connection) {
- throw new Exception('Failed to connect to LDAP server');
- }
-
- // Set LDAP options
- ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, 3);
- ldap_set_option($this->connection, LDAP_OPT_REFERRALS, 0);
-
- // Enable TLS if using port 636
- if ($this->config['port'] == 636) {
- if (!ldap_start_tls($this->connection)) {
- throw new Exception('Failed to start TLS');
- }
- }
- }
-
- private function disconnect() {
- if ($this->connection) {
- ldap_close($this->connection);
- $this->connection = null;
- }
- }
-
- private function getLdapAttribute($entry, $attribute) {
- if (isset($entry[$attribute])) {
- if ($entry[$attribute]['count'] > 1) {
- return $entry[$attribute][0]; // Return first value for multi-valued attributes
- }
- return $entry[$attribute][0];
- }
- return null;
- }
-
- public function searchUsers($query = '', $limit = 50) {
- try {
- $this->connect();
-
- // Bind with service account if configured
- if (!empty($this->config['bind_dn'])) {
- if (!ldap_bind($this->connection, $this->config['bind_dn'], $this->config['bind_password'])) {
- throw new Exception('LDAP bind failed with service account');
- }
- }
-
- // Build search filter
- if ($query) {
- $escaped_query = ldap_escape($query, '', LDAP_ESCAPE_FILTER);
- $filter = "(&(|(uid=*$escaped_query*)(cn=*$escaped_query*)(mail=*$escaped_query*)(givenName=*$escaped_query*)(sn=*$escaped_query*))(!(objectClass=computer)))";
- } else {
- $filter = "(&(objectClass=person)(!(objectClass=computer)))";
- }
-
- $search = ldap_search($this->connection, $this->config['base_dn'], $filter, [
- 'uid',
- 'cn',
- 'givenName',
- 'sn',
- 'mail',
- 'dn'
- ]);
-
- if (!$search) {
- throw new Exception('LDAP search failed');
- }
-
- $entries = ldap_get_entries($this->connection, $search);
-
- $users = [];
- for ($i = 0; $i < $entries['count']; $i++) {
- $user_entry = $entries[$i];
- $users[] = [
- 'username' => $this->getLdapAttribute($user_entry, 'uid'),
- 'name' => $this->getLdapAttribute($user_entry, 'cn'),
- 'first_name' => $this->getLdapAttribute($user_entry, 'givenName'),
- 'last_name' => $this->getLdapAttribute($user_entry, 'sn'),
- 'email' => $this->getLdapAttribute($user_entry, 'mail'),
- 'ldap_dn' => $user_entry['dn']
- ];
- }
-
- return $users;
-
- } catch (Exception $e) {
- error_log('LDAP User Search Error: ' . $e->getMessage());
- return [];
- } finally {
- $this->disconnect();
- }
- }
- }
|