xref: /dokuwiki/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php (revision f4208bec89d316b165212b0c9d1a4f51ab3c4e54)
176ce1169SAndreas Gohr<?php
276ce1169SAndreas Gohr/**
376ce1169SAndreas Gohr * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
476ce1169SAndreas Gohr * Version 4.0.4
576ce1169SAndreas Gohr *
676ce1169SAndreas Gohr * PHP Version 5 with SSL and LDAP support
776ce1169SAndreas Gohr *
876ce1169SAndreas Gohr * Written by Scott Barnett, Richard Hyland
976ce1169SAndreas Gohr *   email: scott@wiggumworld.com, adldap@richardhyland.com
1076ce1169SAndreas Gohr *   http://adldap.sourceforge.net/
1176ce1169SAndreas Gohr *
1276ce1169SAndreas Gohr * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
1376ce1169SAndreas Gohr *
1476ce1169SAndreas Gohr * We'd appreciate any improvements or additions to be submitted back
1576ce1169SAndreas Gohr * to benefit the entire community :)
1676ce1169SAndreas Gohr *
1776ce1169SAndreas Gohr * This library is free software; you can redistribute it and/or
1876ce1169SAndreas Gohr * modify it under the terms of the GNU Lesser General Public
1976ce1169SAndreas Gohr * License as published by the Free Software Foundation; either
2076ce1169SAndreas Gohr * version 2.1 of the License.
2176ce1169SAndreas Gohr *
2276ce1169SAndreas Gohr * This library is distributed in the hope that it will be useful,
2376ce1169SAndreas Gohr * but WITHOUT ANY WARRANTY; without even the implied warranty of
2476ce1169SAndreas Gohr * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2576ce1169SAndreas Gohr * Lesser General Public License for more details.
2676ce1169SAndreas Gohr *
2776ce1169SAndreas Gohr * @category ToolsAndUtilities
2876ce1169SAndreas Gohr * @package adLDAP
2976ce1169SAndreas Gohr * @subpackage Utils
3076ce1169SAndreas Gohr * @author Scott Barnett, Richard Hyland
3176ce1169SAndreas Gohr * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
3276ce1169SAndreas Gohr * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
3376ce1169SAndreas Gohr * @revision $Revision: 97 $
3476ce1169SAndreas Gohr * @version 4.0.4
3576ce1169SAndreas Gohr * @link http://adldap.sourceforge.net/
3676ce1169SAndreas Gohr */
3776ce1169SAndreas Gohrrequire_once(dirname(__FILE__) . '/../adLDAP.php');
3876ce1169SAndreas Gohr
3976ce1169SAndreas Gohr/**
4076ce1169SAndreas Gohr* UTILITY FUNCTIONS
4176ce1169SAndreas Gohr*/
4276ce1169SAndreas Gohrclass adLDAPUtils {
4376ce1169SAndreas Gohr    const ADLDAP_VERSION = '4.0.4';
4476ce1169SAndreas Gohr
4576ce1169SAndreas Gohr    /**
4676ce1169SAndreas Gohr    * The current adLDAP connection via dependency injection
4776ce1169SAndreas Gohr    *
4876ce1169SAndreas Gohr    * @var adLDAP
4976ce1169SAndreas Gohr    */
5076ce1169SAndreas Gohr    protected $adldap;
5176ce1169SAndreas Gohr
5276ce1169SAndreas Gohr    public function __construct(adLDAP $adldap) {
5376ce1169SAndreas Gohr        $this->adldap = $adldap;
5476ce1169SAndreas Gohr    }
5576ce1169SAndreas Gohr
5676ce1169SAndreas Gohr
5776ce1169SAndreas Gohr    /**
5876ce1169SAndreas Gohr    * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
5976ce1169SAndreas Gohr    *
6076ce1169SAndreas Gohr    * @param array $groups
6176ce1169SAndreas Gohr    * @return array
6276ce1169SAndreas Gohr    */
6376ce1169SAndreas Gohr    public function niceNames($groups)
6476ce1169SAndreas Gohr    {
6576ce1169SAndreas Gohr
6676ce1169SAndreas Gohr        $groupArray = array();
6776ce1169SAndreas Gohr        for ($i=0; $i<$groups["count"]; $i++){ // For each group
6876ce1169SAndreas Gohr            $line = $groups[$i];
6976ce1169SAndreas Gohr
7076ce1169SAndreas Gohr            if (strlen($line)>0) {
7176ce1169SAndreas Gohr                // More presumptions, they're all prefixed with CN=
7276ce1169SAndreas Gohr                // so we ditch the first three characters and the group
7376ce1169SAndreas Gohr                // name goes up to the first comma
7476ce1169SAndreas Gohr                $bits=explode(",", $line);
7576ce1169SAndreas Gohr                $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
7676ce1169SAndreas Gohr            }
7776ce1169SAndreas Gohr        }
7876ce1169SAndreas Gohr        return $groupArray;
7976ce1169SAndreas Gohr    }
8076ce1169SAndreas Gohr
8176ce1169SAndreas Gohr    /**
8276ce1169SAndreas Gohr    * Escape characters for use in an ldap_create function
8376ce1169SAndreas Gohr    *
8476ce1169SAndreas Gohr    * @param string $str
8576ce1169SAndreas Gohr    * @return string
8676ce1169SAndreas Gohr    */
8776ce1169SAndreas Gohr    public function escapeCharacters($str) {
8876ce1169SAndreas Gohr        $str = str_replace(",", "\,", $str);
8976ce1169SAndreas Gohr        return $str;
9076ce1169SAndreas Gohr    }
9176ce1169SAndreas Gohr
9276ce1169SAndreas Gohr    /**
9376ce1169SAndreas Gohr    * Escape strings for the use in LDAP filters
9476ce1169SAndreas Gohr    *
9576ce1169SAndreas Gohr    * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
9676ce1169SAndreas Gohr    * Ported from Perl's Net::LDAP::Util escape_filter_value
9776ce1169SAndreas Gohr    *
9876ce1169SAndreas Gohr    * @param string $str The string the parse
9976ce1169SAndreas Gohr    * @author Port by Andreas Gohr <andi@splitbrain.org>
10076ce1169SAndreas Gohr    * @return string
10176ce1169SAndreas Gohr    */
102*f4208becSGerrit Uitslag    protected function ldapSlashes($str) {
103*f4208becSGerrit Uitslag        // see https://github.com/adldap/adLDAP/issues/22
104*f4208becSGerrit Uitslag        return preg_replace_callback(
105*f4208becSGerrit Uitslag            '/([\x00-\x1F\*\(\)\\\\])/',
106*f4208becSGerrit Uitslag            function ($matches) {
107*f4208becSGerrit Uitslag                return "\\".join("", unpack("H2", $matches[1]));
108*f4208becSGerrit Uitslag            },
109*f4208becSGerrit Uitslag            $str
110*f4208becSGerrit Uitslag        );
11176ce1169SAndreas Gohr    }
11276ce1169SAndreas Gohr    /**
11376ce1169SAndreas Gohr    * Converts a string GUID to a hexdecimal value so it can be queried
11476ce1169SAndreas Gohr    *
11576ce1169SAndreas Gohr    * @param string $strGUID A string representation of a GUID
11676ce1169SAndreas Gohr    * @return string
11776ce1169SAndreas Gohr    */
11876ce1169SAndreas Gohr    public function strGuidToHex($strGUID)
11976ce1169SAndreas Gohr    {
12076ce1169SAndreas Gohr        $strGUID = str_replace('-', '', $strGUID);
12176ce1169SAndreas Gohr
12276ce1169SAndreas Gohr        $octet_str = '\\' . substr($strGUID, 6, 2);
12376ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 4, 2);
12476ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 2, 2);
12576ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 0, 2);
12676ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 10, 2);
12776ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 8, 2);
12876ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 14, 2);
12976ce1169SAndreas Gohr        $octet_str .= '\\' . substr($strGUID, 12, 2);
13076ce1169SAndreas Gohr        //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
13176ce1169SAndreas Gohr        for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
13276ce1169SAndreas Gohr            if (($i % 2) == 0) {
13376ce1169SAndreas Gohr                $octet_str .= '\\' . substr($strGUID, $i, 2);
13476ce1169SAndreas Gohr            }
13576ce1169SAndreas Gohr        }
13676ce1169SAndreas Gohr
13776ce1169SAndreas Gohr        return $octet_str;
13876ce1169SAndreas Gohr    }
13976ce1169SAndreas Gohr
14076ce1169SAndreas Gohr    /**
14176ce1169SAndreas Gohr    * Convert a binary SID to a text SID
14276ce1169SAndreas Gohr    *
14376ce1169SAndreas Gohr    * @param string $binsid A Binary SID
14476ce1169SAndreas Gohr    * @return string
14576ce1169SAndreas Gohr    */
14676ce1169SAndreas Gohr     public function getTextSID($binsid) {
14776ce1169SAndreas Gohr        $hex_sid = bin2hex($binsid);
14876ce1169SAndreas Gohr        $rev = hexdec(substr($hex_sid, 0, 2));
14976ce1169SAndreas Gohr        $subcount = hexdec(substr($hex_sid, 2, 2));
15076ce1169SAndreas Gohr        $auth = hexdec(substr($hex_sid, 4, 12));
15176ce1169SAndreas Gohr        $result = "$rev-$auth";
15276ce1169SAndreas Gohr
15376ce1169SAndreas Gohr        for ($x=0;$x < $subcount; $x++) {
15476ce1169SAndreas Gohr            $subauth[$x] =
15576ce1169SAndreas Gohr                hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
15676ce1169SAndreas Gohr                $result .= "-" . $subauth[$x];
15776ce1169SAndreas Gohr        }
15876ce1169SAndreas Gohr
15976ce1169SAndreas Gohr        // Cheat by tacking on the S-
16076ce1169SAndreas Gohr        return 'S-' . $result;
16176ce1169SAndreas Gohr     }
16276ce1169SAndreas Gohr
16376ce1169SAndreas Gohr    /**
16476ce1169SAndreas Gohr    * Converts a little-endian hex number to one that hexdec() can convert
16576ce1169SAndreas Gohr    *
16676ce1169SAndreas Gohr    * @param string $hex A hex code
16776ce1169SAndreas Gohr    * @return string
16876ce1169SAndreas Gohr    */
16976ce1169SAndreas Gohr     public function littleEndian($hex)
17076ce1169SAndreas Gohr     {
17176ce1169SAndreas Gohr        $result = '';
17276ce1169SAndreas Gohr        for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
17376ce1169SAndreas Gohr            $result .= substr($hex, $x, 2);
17476ce1169SAndreas Gohr        }
17576ce1169SAndreas Gohr        return $result;
17676ce1169SAndreas Gohr     }
17776ce1169SAndreas Gohr
17876ce1169SAndreas Gohr     /**
17976ce1169SAndreas Gohr    * Converts a binary attribute to a string
18076ce1169SAndreas Gohr    *
18176ce1169SAndreas Gohr    * @param string $bin A binary LDAP attribute
18276ce1169SAndreas Gohr    * @return string
18376ce1169SAndreas Gohr    */
18476ce1169SAndreas Gohr    public function binaryToText($bin)
18576ce1169SAndreas Gohr    {
18676ce1169SAndreas Gohr        $hex_guid = bin2hex($bin);
18776ce1169SAndreas Gohr        $hex_guid_to_guid_str = '';
18876ce1169SAndreas Gohr        for($k = 1; $k <= 4; ++$k) {
18976ce1169SAndreas Gohr            $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
19076ce1169SAndreas Gohr        }
19176ce1169SAndreas Gohr        $hex_guid_to_guid_str .= '-';
19276ce1169SAndreas Gohr        for($k = 1; $k <= 2; ++$k) {
19376ce1169SAndreas Gohr            $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
19476ce1169SAndreas Gohr        }
19576ce1169SAndreas Gohr        $hex_guid_to_guid_str .= '-';
19676ce1169SAndreas Gohr        for($k = 1; $k <= 2; ++$k) {
19776ce1169SAndreas Gohr            $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
19876ce1169SAndreas Gohr        }
19976ce1169SAndreas Gohr        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
20076ce1169SAndreas Gohr        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
20176ce1169SAndreas Gohr        return strtoupper($hex_guid_to_guid_str);
20276ce1169SAndreas Gohr    }
20376ce1169SAndreas Gohr
20476ce1169SAndreas Gohr    /**
20576ce1169SAndreas Gohr    * Converts a binary GUID to a string GUID
20676ce1169SAndreas Gohr    *
20776ce1169SAndreas Gohr    * @param string $binaryGuid The binary GUID attribute to convert
20876ce1169SAndreas Gohr    * @return string
20976ce1169SAndreas Gohr    */
21076ce1169SAndreas Gohr    public function decodeGuid($binaryGuid)
21176ce1169SAndreas Gohr    {
21276ce1169SAndreas Gohr        if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
21376ce1169SAndreas Gohr
21476ce1169SAndreas Gohr        $strGUID = $this->binaryToText($binaryGuid);
21576ce1169SAndreas Gohr        return $strGUID;
21676ce1169SAndreas Gohr    }
21776ce1169SAndreas Gohr
21876ce1169SAndreas Gohr    /**
21976ce1169SAndreas Gohr    * Convert a boolean value to a string
22076ce1169SAndreas Gohr    * You should never need to call this yourself
22176ce1169SAndreas Gohr    *
22276ce1169SAndreas Gohr    * @param bool $bool Boolean value
22376ce1169SAndreas Gohr    * @return string
22476ce1169SAndreas Gohr    */
22576ce1169SAndreas Gohr    public function boolToStr($bool)
22676ce1169SAndreas Gohr    {
22776ce1169SAndreas Gohr        return ($bool) ? 'TRUE' : 'FALSE';
22876ce1169SAndreas Gohr    }
22976ce1169SAndreas Gohr
23076ce1169SAndreas Gohr    /**
23176ce1169SAndreas Gohr    * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
23276ce1169SAndreas Gohr    */
23376ce1169SAndreas Gohr    public function encode8Bit(&$item, $key) {
23476ce1169SAndreas Gohr        $encode = false;
23576ce1169SAndreas Gohr        if (is_string($item)) {
23676ce1169SAndreas Gohr            for ($i=0; $i<strlen($item); $i++) {
23776ce1169SAndreas Gohr                if (ord($item[$i]) >> 7) {
23876ce1169SAndreas Gohr                    $encode = true;
23976ce1169SAndreas Gohr                }
24076ce1169SAndreas Gohr            }
24176ce1169SAndreas Gohr        }
24276ce1169SAndreas Gohr        if ($encode === true && $key != 'password') {
24376ce1169SAndreas Gohr            $item = utf8_encode($item);
24476ce1169SAndreas Gohr        }
24576ce1169SAndreas Gohr    }
24676ce1169SAndreas Gohr
24776ce1169SAndreas Gohr    /**
24876ce1169SAndreas Gohr    * Get the current class version number
24976ce1169SAndreas Gohr    *
25076ce1169SAndreas Gohr    * @return string
25176ce1169SAndreas Gohr    */
25276ce1169SAndreas Gohr    public function getVersion() {
25376ce1169SAndreas Gohr        return self::ADLDAP_VERSION;
25476ce1169SAndreas Gohr    }
25576ce1169SAndreas Gohr
25676ce1169SAndreas Gohr    /**
25776ce1169SAndreas Gohr    * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
25876ce1169SAndreas Gohr    *
25976ce1169SAndreas Gohr    * @param long $windowsTime
26076ce1169SAndreas Gohr    * @return long $unixTime
26176ce1169SAndreas Gohr    */
26276ce1169SAndreas Gohr    public static function convertWindowsTimeToUnixTime($windowsTime) {
26376ce1169SAndreas Gohr      $unixTime = round($windowsTime / 10000000) - 11644477200;
26476ce1169SAndreas Gohr      return $unixTime;
26576ce1169SAndreas Gohr    }
26676ce1169SAndreas Gohr}
26776ce1169SAndreas Gohr
26876ce1169SAndreas Gohr?>