1 <?php
2 /**
3  * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
4  * Version 4.0.4
5  *
6  * PHP Version 5 with SSL and LDAP support
7  *
8  * Written by Scott Barnett, Richard Hyland
9  *   email: scott@wiggumworld.com, adldap@richardhyland.com
10  *   http://adldap.sourceforge.net/
11  *
12  * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
13  *
14  * We'd appreciate any improvements or additions to be submitted back
15  * to benefit the entire community :)
16  *
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  *
27  * @category ToolsAndUtilities
28  * @package adLDAP
29  * @subpackage Utils
30  * @author Scott Barnett, Richard Hyland
31  * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
32  * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
33  * @revision $Revision: 97 $
34  * @version 4.0.4
35  * @link http://adldap.sourceforge.net/
36  */
37 require_once(dirname(__FILE__) . '/../adLDAP.php');
38 
39 /**
40 * UTILITY FUNCTIONS
41 */
42 class adLDAPUtils {
43     const ADLDAP_VERSION = '4.0.4';
44 
45     /**
46     * The current adLDAP connection via dependency injection
47     *
48     * @var adLDAP
49     */
50     protected $adldap;
51 
52     public function __construct(adLDAP $adldap) {
53         $this->adldap = $adldap;
54     }
55 
56 
57     /**
58     * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
59     *
60     * @param array $groups
61     * @return array
62     */
63     public function niceNames($groups)
64     {
65 
66         $groupArray = array();
67         for ($i=0; $i<$groups["count"]; $i++){ // For each group
68             $line = $groups[$i];
69 
70             if (strlen($line)>0) {
71                 // More presumptions, they're all prefixed with CN=
72                 // so we ditch the first three characters and the group
73                 // name goes up to the first comma
74                 $bits=explode(",", $line);
75                 $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
76             }
77         }
78         return $groupArray;
79     }
80 
81     /**
82     * Escape characters for use in an ldap_create function
83     *
84     * @param string $str
85     * @return string
86     */
87     public function escapeCharacters($str) {
88         $str = str_replace(",", "\,", $str);
89         return $str;
90     }
91 
92     /**
93     * Escape strings for the use in LDAP filters
94     *
95     * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
96     * Ported from Perl's Net::LDAP::Util escape_filter_value
97     *
98     * @param string $str The string the parse
99     * @author Port by Andreas Gohr <andi@splitbrain.org>
100     * @return string
101     */
102     public function ldapSlashes($str) {
103         // see https://github.com/adldap/adLDAP/issues/22
104         return preg_replace_callback(
105             '/([\x00-\x1F\*\(\)\\\\])/',
106             function ($matches) {
107                 return "\\".join("", unpack("H2", $matches[1]));
108             },
109             $str
110         );
111     }
112     /**
113     * Converts a string GUID to a hexdecimal value so it can be queried
114     *
115     * @param string $strGUID A string representation of a GUID
116     * @return string
117     */
118     public function strGuidToHex($strGUID)
119     {
120         $strGUID = str_replace('-', '', $strGUID);
121 
122         $octet_str = '\\' . substr($strGUID, 6, 2);
123         $octet_str .= '\\' . substr($strGUID, 4, 2);
124         $octet_str .= '\\' . substr($strGUID, 2, 2);
125         $octet_str .= '\\' . substr($strGUID, 0, 2);
126         $octet_str .= '\\' . substr($strGUID, 10, 2);
127         $octet_str .= '\\' . substr($strGUID, 8, 2);
128         $octet_str .= '\\' . substr($strGUID, 14, 2);
129         $octet_str .= '\\' . substr($strGUID, 12, 2);
130         //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
131         for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
132             if (($i % 2) == 0) {
133                 $octet_str .= '\\' . substr($strGUID, $i, 2);
134             }
135         }
136 
137         return $octet_str;
138     }
139 
140     /**
141     * Convert a binary SID to a text SID
142     *
143     * @param string $binsid A Binary SID
144     * @return string
145     */
146      public function getTextSID($binsid) {
147         $hex_sid = bin2hex($binsid);
148         $rev = hexdec(substr($hex_sid, 0, 2));
149         $subcount = hexdec(substr($hex_sid, 2, 2));
150         $auth = hexdec(substr($hex_sid, 4, 12));
151         $result = "$rev-$auth";
152 
153         for ($x=0;$x < $subcount; $x++) {
154             $subauth[$x] =
155                 hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
156                 $result .= "-" . $subauth[$x];
157         }
158 
159         // Cheat by tacking on the S-
160         return 'S-' . $result;
161      }
162 
163     /**
164     * Converts a little-endian hex number to one that hexdec() can convert
165     *
166     * @param string $hex A hex code
167     * @return string
168     */
169      public function littleEndian($hex)
170      {
171         $result = '';
172         for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
173             $result .= substr($hex, $x, 2);
174         }
175         return $result;
176      }
177 
178      /**
179     * Converts a binary attribute to a string
180     *
181     * @param string $bin A binary LDAP attribute
182     * @return string
183     */
184     public function binaryToText($bin)
185     {
186         $hex_guid = bin2hex($bin);
187         $hex_guid_to_guid_str = '';
188         for($k = 1; $k <= 4; ++$k) {
189             $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
190         }
191         $hex_guid_to_guid_str .= '-';
192         for($k = 1; $k <= 2; ++$k) {
193             $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
194         }
195         $hex_guid_to_guid_str .= '-';
196         for($k = 1; $k <= 2; ++$k) {
197             $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
198         }
199         $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
200         $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
201         return strtoupper($hex_guid_to_guid_str);
202     }
203 
204     /**
205     * Converts a binary GUID to a string GUID
206     *
207     * @param string $binaryGuid The binary GUID attribute to convert
208     * @return string
209     */
210     public function decodeGuid($binaryGuid)
211     {
212         if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
213 
214         $strGUID = $this->binaryToText($binaryGuid);
215         return $strGUID;
216     }
217 
218     /**
219     * Convert a boolean value to a string
220     * You should never need to call this yourself
221     *
222     * @param bool $bool Boolean value
223     * @return string
224     */
225     public function boolToStr($bool)
226     {
227         return ($bool) ? 'TRUE' : 'FALSE';
228     }
229 
230     /**
231     * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
232     */
233     public function encode8Bit(&$item, $key) {
234         $encode = false;
235         if (is_string($item)) {
236             for ($i=0; $i<strlen($item); $i++) {
237                 if (ord($item[$i]) >> 7) {
238                     $encode = true;
239                 }
240             }
241         }
242         if ($encode === true && $key != 'password') {
243             $item = utf8_encode($item);
244         }
245     }
246 
247     /**
248     * Get the current class version number
249     *
250     * @return string
251     */
252     public function getVersion() {
253         return self::ADLDAP_VERSION;
254     }
255 
256     /**
257     * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
258     *
259     * @param long $windowsTime
260     * @return long $unixTime
261     */
262     public static function convertWindowsTimeToUnixTime($windowsTime) {
263       $unixTime = round($windowsTime / 10000000) - 11644477200;
264       return $unixTime;
265     }
266 }
267 
268 ?>
269