function change_password($ldap, $dn, $password, $ad_mode, $ad_options, $samba_mode, $shadow_options, $hash, $who_change_password)
{
    $result = "";
    # Set Samba password value
    if ($samba_mode) {
        $userdata["sambaNTPassword"] = make_md4_password($password);
        $userdata["sambaPwdLastSet"] = time();
    }
    # Transform password value
    if ($ad_mode) {
        $password = make_ad_password($password);
    } else {
        # Hash password if needed
        if ($hash == "SSHA") {
            $password = make_ssha_password($password);
        }
        if ($hash == "SHA") {
            $password = make_sha_password($password);
        }
        if ($hash == "SMD5") {
            $password = make_smd5_password($password);
        }
        if ($hash == "MD5") {
            $password = make_md5_password($password);
        }
        if ($hash == "CRYPT") {
            $password = make_crypt_password($password);
        }
    }
    # Set password value
    if ($ad_mode) {
        $userdata["unicodePwd"] = $password;
        if ($ad_options['force_unlock']) {
            $userdata["lockoutTime"] = 0;
        }
        if ($ad_options['force_pwd_change']) {
            $userdata["pwdLastSet"] = 0;
        }
    } else {
        $userdata["userPassword"] = $password;
    }
    # Shadow options
    if ($shadow_options['update_shadowLastChange']) {
        $userdata["shadowLastChange"] = floor(time() / 86400);
    }
    # Commit modification on directory
    # Special case: AD mode with password changed as user
    # Not possible with PHP, because requires add/delete modification
    # in a single operation
    if ($ad_mode and $who_change_password === "user") {
        $result = "passworderror";
        error_log("Cannot modify AD password as user");
        return $result;
    }
    # Else just replace with new password
    $replace = ldap_mod_replace($ldap, $dn, $userdata);
    $errno = ldap_errno($ldap);
    if ($errno) {
        $result = "passworderror";
        error_log("LDAP - Modify password error {$errno} (" . ldap_error($ldap) . ")");
    } else {
        $result = "passwordchanged";
    }
    return $result;
}
function change_password($ldap, $dn, $password, $ad_mode, $ad_options, $samba_mode, $samba_options, $shadow_options, $hash, $hash_options, $who_change_password, $oldpassword)
{
    $result = "";
    $time = time();
    # Set Samba password value
    if ($samba_mode) {
        $userdata["sambaNTPassword"] = make_md4_password($password);
        $userdata["sambaPwdLastSet"] = $time;
        if (isset($samba_options['min_age']) && $samba_options['min_age'] > 0) {
            $userdata["sambaPwdCanChange"] = $time + $samba_options['min_age'] * 86400;
        }
        if (isset($samba_options['max_age']) && $samba_options['max_age'] > 0) {
            $userdata["sambaPwdMustChange"] = $time + $samba_options['max_age'] * 86400;
        }
    }
    # Get hash type if hash is set to auto
    if (!$ad_mode && $hash == "auto") {
        $search_userpassword = ldap_read($ldap, $dn, "(objectClass=*)", array("userPassword"));
        if ($search_userpassword) {
            $userpassword = ldap_get_values($ldap, ldap_first_entry($ldap, $search_userpassword), "userPassword");
            if (isset($userpassword)) {
                if (preg_match('/^\\{(\\w+)\\}/', $userpassword[0], $matches)) {
                    $hash = strtoupper($matches[1]);
                }
            }
        }
    }
    # Transform password value
    if ($ad_mode) {
        $password = make_ad_password($password);
    } else {
        # Hash password if needed
        if ($hash == "SSHA") {
            $password = make_ssha_password($password);
        }
        if ($hash == "SHA") {
            $password = make_sha_password($password);
        }
        if ($hash == "SMD5") {
            $password = make_smd5_password($password);
        }
        if ($hash == "MD5") {
            $password = make_md5_password($password);
        }
        if ($hash == "CRYPT") {
            $password = make_crypt_password($password, $hash_options);
        }
    }
    # Set password value
    if ($ad_mode) {
        $userdata["unicodePwd"] = $password;
        if ($ad_options['force_unlock']) {
            $userdata["lockoutTime"] = 0;
        }
        if ($ad_options['force_pwd_change']) {
            $userdata["pwdLastSet"] = 0;
        }
    } else {
        $userdata["userPassword"] = $password;
    }
    # Shadow options
    if ($shadow_options['update_shadowLastChange']) {
        $userdata["shadowLastChange"] = floor($time / 86400);
    }
    # Commit modification on directory
    # Special case: AD mode with password changed as user
    if ($ad_mode and $who_change_password === "user") {
        # The AD password change procedure is modifying the attribute unicodePwd by
        # first deleting unicodePwd with the old password and them adding it with the
        # the new password
        $oldpassword = make_ad_password($oldpassword);
        $modifications = array(array("attrib" => "unicodePwd", "modtype" => LDAP_MODIFY_BATCH_REMOVE, "values" => array($oldpassword)), array("attrib" => "unicodePwd", "modtype" => LDAP_MODIFY_BATCH_ADD, "values" => array($password)));
        $bmod = ldap_modify_batch($ldap, $dn, $modifications);
    } else {
        # Else just replace with new password
        $replace = ldap_mod_replace($ldap, $dn, $userdata);
    }
    $errno = ldap_errno($ldap);
    if ($errno) {
        $result = "passworderror";
        error_log("LDAP - Modify password error {$errno} (" . ldap_error($ldap) . ")");
    } else {
        $result = "passwordchanged";
    }
    return $result;
}