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