Subversion Repositories php_utils

Rev

Rev 77 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 77 Rev 89
1
<?php
1
<?php
2
 
2
 
3
/*
3
/*
4
 * VtsLDAPUtils - Simple LDAP helper functions
4
 * VtsLDAPUtils - Simple LDAP helper functions
5
 * Copyright 2021 - 2023 Daniel Marschall, ViaThinkSoft
5
 * Copyright 2021 - 2023 Daniel Marschall, ViaThinkSoft
6
 * Revision: 2023-04-09
6
 * Revision: 2023-11-30
7
 *
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
10
 * You may obtain a copy of the License at
11
 *
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
18
 * limitations under the License.
19
 */
19
 */
20
 
20
 
21
class VtsLDAPUtils {
21
class VtsLDAPUtils {
22
 
22
 
23
        protected $conn = null;
23
        protected $conn = null;
24
 
24
 
25
        private static function _L(string $str, ...$sprintfArgs): string {
25
        private static function _L(string $str, ...$sprintfArgs): string {
26
                if (function_exists('_L')) {
26
                if (function_exists('_L')) {
27
                        return _L($str, $sprintfArgs);
27
                        return _L($str, $sprintfArgs);
28
                } else if (function_exists('my_vsprintf')) {
28
                } else if (function_exists('my_vsprintf')) {
29
                        return my_vsprintf($str, $sprintfArgs);
29
                        return my_vsprintf($str, $sprintfArgs);
30
                } else {
30
                } else {
31
                        $n = 1;
31
                        $n = 1;
32
                        foreach ($sprintfArgs as $val) {
32
                        foreach ($sprintfArgs as $val) {
33
                                $str = str_replace("%$n", $val, $str);
33
                                $str = str_replace("%$n", $val, $str);
34
                                $n++;
34
                                $n++;
35
                        }
35
                        }
36
                        $str = str_replace("%%", "%", $str);
36
                        $str = str_replace("%%", "%", $str);
37
                        return $str;
37
                        return $str;
38
                }
38
                }
39
        }
39
        }
40
 
40
 
41
        public static function getString($ldap_userinfo, $attributeName) {
41
        public static function getString($ldap_userinfo, $attributeName) {
42
                $ary = self::getArray($ldap_userinfo, $attributeName);
42
                $ary = self::getArray($ldap_userinfo, $attributeName);
43
                return implode("\n", $ary);
43
                return implode("\n", $ary);
44
        }
44
        }
45
 
45
 
46
        public static function getArray($ldap_userinfo, $attributeName) {
46
        public static function getArray($ldap_userinfo, $attributeName) {
47
                $ary = array();
47
                $ary = array();
48
                if (isset($ldap_userinfo[$attributeName])) {
48
                if (isset($ldap_userinfo[$attributeName])) {
49
                        $cnt = $ldap_userinfo[$attributeName]['count'];
49
                        $cnt = $ldap_userinfo[$attributeName]['count'];
50
                        for ($i=0; $i<$cnt; $i++) {
50
                        for ($i=0; $i<$cnt; $i++) {
51
                                $ary[] = $ldap_userinfo[$attributeName][$i];
51
                                $ary[] = $ldap_userinfo[$attributeName][$i];
52
                        }
52
                        }
53
                }
53
                }
54
                return $ary;
54
                return $ary;
55
        }
55
        }
56
 
56
 
57
        public function isMemberOfRec($userDN, $groupDN) {
57
        public function isMemberOfRec($userDN, $groupDN) {
58
 
58
 
59
                if (isset($userDN['dn'])) $userDN = $userDN['dn'];
59
                if (isset($userDN['dn'])) $userDN = $userDN['dn'];
60
                if (isset($groupDN['dn'])) $groupDN = $groupDN['dn'];
60
                if (isset($groupDN['dn'])) $groupDN = $groupDN['dn'];
61
 
61
 
62
                if (!$this->conn) throw new Exception('LDAP not connected');
62
                if (!$this->conn) throw new Exception('LDAP not connected');
63
                $res = ldap_read($this->conn, $groupDN, "(objectClass=*)");
63
                $res = ldap_read($this->conn, $groupDN, "(objectClass=*)");
64
                if (!$res) return false;
64
                if (!$res) return false;
65
                $entries = ldap_get_entries($this->conn, $res);
65
                $entries = ldap_get_entries($this->conn, $res);
66
                if (!isset($entries[0])) return false;
66
                if (!isset($entries[0])) return false;
67
                if (!isset($entries[0]['member'])) return false;
67
                if (!isset($entries[0]['member'])) return false;
68
                if (!isset($entries[0]['member']['count'])) return false;
68
                if (!isset($entries[0]['member']['count'])) return false;
69
                $cntMember = $entries[0]['member']['count'];
69
                $cntMember = $entries[0]['member']['count'];
70
                for ($iMember=0; $iMember<$cntMember; $iMember++) {
70
                for ($iMember=0; $iMember<$cntMember; $iMember++) {
71
                        $groupOrUser = $entries[0]['member'][$iMember];
71
                        $groupOrUser = $entries[0]['member'][$iMember];
72
                        if (strtolower($groupOrUser) == strtolower($userDN)) return true;
72
                        if (strtolower($groupOrUser) == strtolower($userDN)) return true;
73
                        if ($this->isMemberOfRec($userDN, $groupOrUser)) return true;
73
                        if ($this->isMemberOfRec($userDN, $groupOrUser)) return true;
74
                }
74
                }
75
                return false;
75
                return false;
76
        }
76
        }
77
 
77
 
78
        public function __destruct() {
78
        public function __destruct() {
79
                $this->disconnect();
79
                $this->disconnect();
80
        }
80
        }
81
 
81
 
82
        public function disconnect() {
82
        public function disconnect() {
83
                if ($this->conn) {
83
                if ($this->conn) {
84
                        //ldap_unbind($this->conn); // commented out because ldap_unbind() kills the link descriptor
84
                        //ldap_unbind($this->conn); // commented out because ldap_unbind() kills the link descriptor
85
                        ldap_close($this->conn);
85
                        ldap_close($this->conn);
86
                        $this->conn = null;
86
                        $this->conn = null;
87
                }
87
                }
88
        }
88
        }
89
 
89
 
90
        public function connect($cfg_ldap_server, $cfg_ldap_port) {
90
        public function connect($cfg_ldap_server, $cfg_ldap_port=389) {
91
                $this->disconnect();
91
                $this->disconnect();
92
 
92
 
93
                // Connect to the server
93
                // Connect to the server
94
                if (!empty($cfg_ldap_port)) {
94
                if (strpos($cfg_ldap_server, '://') !== false) {
95
                        if (!($ldapconn = @ldap_connect($cfg_ldap_server, $cfg_ldap_port))) throw new Exception(self::_L('Cannot connect to LDAP server'));
95
                        // e.g. ldap://hostname:port or ldaps://hostname:port
-
 
96
                        $uri = $cfg_ldap_server;
96
                } else {
97
                } else {
97
                        if (!($ldapconn = @ldap_connect($cfg_ldap_server))) throw new Exception(self::_L('Cannot connect to LDAP server'));
98
                        $secure = ($cfg_ldap_port == 636) || ($cfg_ldap_port == 3268) || ($cfg_ldap_port == 3269);
-
 
99
                        $schema = $secure ? 'ldaps' : 'ldap';
-
 
100
                        $uri =  $schema . '://' . $cfg_ldap_server . ':' . $cfg_ldap_port;
98
                }
101
                }
-
 
102
                if (!($ldapconn = @ldap_connect($uri))) throw new Exception(self::_L('Cannot connect to LDAP server'));
-
 
103
 
99
                ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
104
                ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
100
                ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
105
                ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
101
 
106
 
102
                $this->conn = $ldapconn;
107
                $this->conn = $ldapconn;
103
        }
108
        }
104
 
109
 
105
        public function login($username, $password) {
110
        public function login($username, $password) {
106
                return @ldap_bind($this->conn, $username, $password);
111
                return @ldap_bind($this->conn, $username, $password);
107
        }
112
        }
108
 
113
 
109
        public function getUserInfo($userPrincipalName, $cfg_ldap_base_dn) {
114
        public function getUserInfo($userPrincipalName, $cfg_ldap_base_dn) {
110
                $cfg_ldap_user_filter = "(&(objectClass=user)(objectCategory=person)(userPrincipalName=".ldap_escape($userPrincipalName, '', LDAP_ESCAPE_FILTER)."))";
115
                $cfg_ldap_user_filter = "(&(objectClass=user)(objectCategory=person)(userPrincipalName=".ldap_escape($userPrincipalName, '', LDAP_ESCAPE_FILTER)."))";
111
 
116
 
112
                if (!($result = @ldap_search($this->conn,$cfg_ldap_base_dn, $cfg_ldap_user_filter))) throw new Exception(self::_L('Error in search query: %1', ldap_error($this->conn)));
117
                if (!($result = @ldap_search($this->conn,$cfg_ldap_base_dn, $cfg_ldap_user_filter))) throw new Exception(self::_L('Error in search query: %1', ldap_error($this->conn)));
113
                $data = ldap_get_entries($this->conn, $result);
118
                $data = ldap_get_entries($this->conn, $result);
114
                $ldap_userinfo = array();
119
                $ldap_userinfo = array();
115
 
120
 
116
                if ($data['count'] == 0) return false; /* @phpstan-ignore-line */
121
                if ($data['count'] == 0) return false; /* @phpstan-ignore-line */
117
                $ldap_userinfo = $data[0];
122
                $ldap_userinfo = $data[0];
118
 
123
 
119
                // empty($ldap_userinfo) can happen if the user did not log-in using their correct userPrincipalName (e.g. "username@domainname" instead of "username@domainname.local")
124
                // empty($ldap_userinfo) can happen if the user did not log-in using their correct userPrincipalName (e.g. "username@domainname" instead of "username@domainname.local")
120
                return empty($ldap_userinfo) ? false : $ldap_userinfo;
125
                return empty($ldap_userinfo) ? false : $ldap_userinfo;
121
        }
126
        }
122
 
127
 
123
}
128
}
124
 
129