Subversion Repositories php_utils

Rev

Rev 77 | Details | Compare with Previous | Last modification | View Log | RSS feed

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