Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP ldap_add function to escape ldap special characters in DN syntax

I'm trying to add some users to my Ldap DB but I get some errors (invalid dn syntax) when I use some special characters like ",.". I need a function that escape all characters. I try preg_quote but I get some errors in some cases.

Thanks in advance

Code:

$user = 'Test , Name S.L';

    if(!(ldap_add($ds, "cn=" . $user . ",".LDAP_DN_BASE, $info))) {

            include 'error_new_account.php';

    }
like image 977
Sbml Avatar asked Dec 19 '11 11:12

Sbml


2 Answers

EDIT Jan 2013: added support for escaping leading/trailing spaces in DN strings, per RFC 4514. Thanks to Eugenio for pointing out this issue.

EDIT 2014: I added this function to PHP 5.6. The code below is now a like-for-like drop-in replacement for earlier PHP versions.

if (!function_exists('ldap_escape')) {
    define('LDAP_ESCAPE_FILTER', 0x01);
    define('LDAP_ESCAPE_DN',     0x02);

    /**
     * @param string $subject The subject string
     * @param string $ignore Set of characters to leave untouched
     * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the
     *                   set(s) of characters to escape.
     * @return string
     */
    function ldap_escape($subject, $ignore = '', $flags = 0)
    {
        static $charMaps = array(
            LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"),
            LDAP_ESCAPE_DN     => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'),
        );

        // Pre-process the char maps on first call
        if (!isset($charMaps[0])) {
            $charMaps[0] = array();
            for ($i = 0; $i < 256; $i++) {
                $charMaps[0][chr($i)] = sprintf('\\%02x', $i);;
            }

            for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) {
                $chr = $charMaps[LDAP_ESCAPE_FILTER][$i];
                unset($charMaps[LDAP_ESCAPE_FILTER][$i]);
                $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr];
            }

            for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) {
                $chr = $charMaps[LDAP_ESCAPE_DN][$i];
                unset($charMaps[LDAP_ESCAPE_DN][$i]);
                $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr];
            }
        }

        // Create the base char map to escape
        $flags = (int)$flags;
        $charMap = array();
        if ($flags & LDAP_ESCAPE_FILTER) {
            $charMap += $charMaps[LDAP_ESCAPE_FILTER];
        }
        if ($flags & LDAP_ESCAPE_DN) {
            $charMap += $charMaps[LDAP_ESCAPE_DN];
        }
        if (!$charMap) {
            $charMap = $charMaps[0];
        }

        // Remove any chars to ignore from the list
        $ignore = (string)$ignore;
        for ($i = 0, $l = strlen($ignore); $i < $l; $i++) {
            unset($charMap[$ignore[$i]]);
        }

        // Do the main replacement
        $result = strtr($subject, $charMap);

        // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed
        if ($flags & LDAP_ESCAPE_DN) {
            if ($result[0] === ' ') {
                $result = '\\20' . substr($result, 1);
            }
            if ($result[strlen($result) - 1] === ' ') {
                $result = substr($result, 0, -1) . '\\20';
            }
        }

        return $result;
    }
}

So you would do:

$user = 'Test , Name S.L';
$cn = ldap_escape($user, '', LDAP_ESCAPE_DN);
if (!ldap_add($ds, "cn={$cn}," . LDAP_DN_BASE, $info)) {
    include 'error_new_account.php';
}
like image 108
DaveRandom Avatar answered Oct 28 '22 20:10

DaveRandom


PHP 5.6 Beta released ldap_escape() function recently and it is in effect, However, this version is not production ready at present, you can very use it for your development purposes as of now.

like image 3
Shankar Narayana Damodaran Avatar answered Oct 28 '22 21:10

Shankar Narayana Damodaran