Skip to content

Commit

Permalink
various refactoring around changecustompasswordfield feature (ltb-pro…
Browse files Browse the repository at this point in the history
…ject#864)

- fix change_password() call in changecustompwdfield
- fix check_password call in check_password_strength function
- improve custom password field documentation
- add new custom password parameters in default configuration file
- add missing parameters in custompwdfield doc
- clean default values in changecustompwdfield
- isolate policy parameter: pwd_unique_across_custom_password_fields
- fix tests (new param pwd_unique_across_custom_password_fields)
- add documentation for prehook / posthook in custompwdfield
- improve code readibility
- remove useless check for entropy page (ltb-project#830, ltb-project#864)
- always consider checkentropy as an available action (ltb-project#830, ltb-project#864)
- remove useless test (already done in ltb-ldap project)
- adapt changecustompwdfield.tpl to bootstrap 5.3 upgrade
- improve condition for testing check_password_strength
  • Loading branch information
David Coutadeur authored and davidcoutadeur committed Apr 17, 2024
1 parent 32d255d commit e458c7e
Show file tree
Hide file tree
Showing 37 changed files with 198 additions and 245 deletions.
4 changes: 4 additions & 0 deletions conf/config.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,12 @@
# change
# sendtoken
# sendsms
# changecustompwdfield
$default_action = "change";

## default page of custom password field to display
#$default_custompwdindex = 0;

## Rest API
$use_restapi = false;

Expand Down
87 changes: 55 additions & 32 deletions docs/config_custompwdfield.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,67 +67,90 @@ Possible configuration keys
* - Key
- Description
- default value
* - 'use_captcha'
* - ``attribute``
- LDAP attribute name
- none
* - ``hash``
- hash algorithm. Possible values are the one listed in Ltb\Password library: clear, SSHA, SSHA256, SSHA384, SSHA512, SHA, SHA256, SHA384, SHA512, SMD5, MD5, CRYPT, ARGON2, NTLM
- none
* - ``hash_options``
- array containing prefix and length options for salt when using CRYPT hash
- same value as the general $hash_options
* - ``use_captcha``
- whether or not a captcha must be filled before changing the custom password
- same as for the main password
* - 'label'
- what name should be used on the website?
* - ``label``
- Name of the application or the LDAP attribute to display
- 'Custom Password X', where 'X' is a number starting with 0
* - 'who_change_password'
- does the user or manager change the LDAP-Attribute?
* - ``who_change_password``
- who change the LDAP attribute? Possible values are "manager" or "user"
- same as for the main password
* - 'msg_changehelpextramessage'
* - ``msg_changehelpextramessage``
- An extra message presented to the user, for example "this password is meant for that application"
- empty
* - 'notify_on_change'
* - ``notify_on_change``
- whether or not the user should be notified by email.
- same as for the main password
* - 'ldap_use_ppolicy_control'
- It is possible to set up additional ppolicies on the LDAP Server. If so, you may choose if you want to use them.
* - ``ldap_use_ppolicy_control``
- Do you want to change the LDAP attribute by sending a ppolicy control? (true or false) Most of the time useless, as custom password fields are not subject to password policies.
- false
* - 'pwd_policy_config'
- This is an array containing additional password policies for each custom password field. see below
* - ``pwd_policy_config``
- Array containing additional password policies for each custom password field. see below
- same as for the main password
* - ``prehook``
- path to a script called before password change
- none
* - ``prehook_password_encodebase64``
- boolean. Does the password needs to be base64 encoded before sent to prehook script?
- none
* - ``posthook``
- path to a script called after password change
- none
* - ``posthook_password_encodebase64``
- boolean. Does the password needs to be base64 encoded before sent to posthook script?
- none

.. list-table:: pwd_policy_config array keys
:widths: 50 50
:header-rows: 1

* - Key
- Description
* - 'pwd_show_policy'
* - ``pwd_show_policy``
- Whether or not to show the policy
* - 'pwd_no_reuse'
* - ``pwd_no_reuse``
- whether or not the custom password may be the same as the main password
* - 'pwd_diff_last_min_chars'
* - ``pwd_unique_across_custom_password_fields``
- boolean. if true, the new password must be different from all other custom password marked as unique
* - ``pwd_diff_last_min_chars``
- how many characters of the custom password may be the same as the main password?
* - 'pwd_min_length'
* - ``pwd_min_length``
- minimum length
* - 'pwd_max_length'
* - ``pwd_max_length``
- maximum length
* - 'pwd_min_lower'
* - ``pwd_min_lower``
- minimum lower characters
* - 'pwd_min_upper'
* - ``pwd_min_upper``
- minimum upper characters
* - 'pwd_min_digit'
* - ``pwd_min_digit``
- minimum digits
* - 'pwd_min_special'
* - ``pwd_min_special``
- minimum of special characters
* - 'pwd_special_chars'
* - ``pwd_special_chars``
- what are special characters?
* - 'pwd_forbidden_chars'
* - ``pwd_forbidden_chars``
- forbidden characters
* - 'pwd_diff_login'
* - ``pwd_diff_login``
- whether or not the custom password may be the same as the login-name
* - 'pwd_complexity'
* - ``pwd_complexity``
- number of different class of character required
* - 'use_pwnedpasswords'
* - ``use_pwnedpasswords``
- use pwnedpasswords api v2 to securely check if the password has been on a leak
* - 'pwd_no_special_at_ends'
-
* - 'pwd_forbidden_words'
* - ``pwd_no_special_at_ends``
- forbid to have a special character (as defined by ``pwd_special_chars``) at the beginning or at the end of the password
* - ``pwd_forbidden_words``
- array of forbidden words
* - 'pwd_forbidden_ldap_fields'
- array of attributes which values may not be used in the password
* - 'pwd_show_policy_pos'
- where shall the the password be shown? ("above", "below")
* - ``pwd_forbidden_ldap_fields``
- array of attributes which values must not be used in the password
* - ``pwd_show_policy_pos``
- where shall the password be shown? ("above", "below")
2 changes: 1 addition & 1 deletion htdocs/change.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
#==============================================================================
# Check password strength
#==============================================================================
if ( $result === "" ) {
if ( !$result ) {
$result = check_password_strength( $newpassword, $oldpassword, $pwd_policy_config, $login, $entry_array, $change_custompwdfield );
}

Expand Down
193 changes: 71 additions & 122 deletions htdocs/changecustompwdfield.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@
#
#==============================================================================

# require_once("../lib/LtbAttributeValue_class.php");
# Set a default value if the variable is not initialized
function set_default_value(&$variable, $defaultValue)
{
if(!isset($variable))
{
$variable = $defaultValue;
}

}

#==============================================================================
# POST parameters
Expand Down Expand Up @@ -62,6 +70,7 @@
}
}

# Load custompwdfield configuration corresponding to the index
$custompwdfield = $change_custompwdfield[$custompwdindex];

# Check the entered username for characters that our installation doesn't support
Expand All @@ -80,107 +89,46 @@
#==============================================================================
# Default configuration
#==============================================================================
if (!isset($custompwdfield['ldap_use_ppolicy_control'])) {
$custompwdfield['ldap_use_ppolicy_control'] = false;
} //it is possible to define different password policies for multiple attributes, as far as I know only in OpenLDAP
if (!isset($custompwdfield['pwd_policy_config'])) {
$custompwdfield['pwd_policy_config'] = array();
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_show_policy'])) {
$custompwdfield['pwd_policy_config']['pwd_show_policy'] = $pwd_show_policy;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_min_length'])) {
$custompwdfield['pwd_policy_config']['pwd_min_length'] = $pwd_min_length;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_max_length'])) {
$custompwdfield['pwd_policy_config']['pwd_max_length'] = $pwd_max_length;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_min_lower'])) {
$custompwdfield['pwd_policy_config']['pwd_min_lower'] = $pwd_min_lower;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_min_upper'])) {
$custompwdfield['pwd_policy_config']['pwd_min_upper'] = $pwd_min_upper;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_min_digit'])) {
$custompwdfield['pwd_policy_config']['pwd_min_digit'] = $pwd_min_digit;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_min_special'])) {
$custompwdfield['pwd_policy_config']['pwd_min_special'] = $pwd_min_special;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_special_chars'])) {
$custompwdfield['pwd_policy_config']['pwd_special_chars'] = $pwd_special_chars;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_forbidden_chars'])) {
$custompwdfield['pwd_policy_config']['pwd_forbidden_chars'] = "";
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_no_reuse'])) {
$custompwdfield['pwd_policy_config']['pwd_no_reuse'] = $pwd_no_reuse;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_diff_last_min_chars'])) {
$custompwdfield['pwd_policy_config']['pwd_diff_last_min_chars'] = $pwd_diff_last_min_chars;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_diff_login'])) {
$custompwdfield['pwd_policy_config']['pwd_diff_login'] = $pwd_diff_login;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_complexity'])) {
$custompwdfield['pwd_policy_config']['pwd_complexity'] = $pwd_complexity;
}
if (!isset($custompwdfield['pwd_policy_config']['use_pwnedpasswords'])) {
$custompwdfield['pwd_policy_config']['use_pwnedpasswords'] = $use_pwnedpasswords;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_no_special_at_ends'])) {
$custompwdfield['pwd_policy_config']['pwd_no_special_at_ends'] = $pwd_no_special_at_ends;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_forbidden_words'])) {
$custompwdfield['pwd_policy_config']['pwd_forbidden_words'] = $pwd_forbidden_words;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_forbidden_ldap_fields'])) {
$custompwdfield['pwd_policy_config']['pwd_forbidden_ldap_fields'] = $pwd_forbidden_ldap_fields;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_show_policy_pos'])) {
$custompwdfield['pwd_policy_config']['pwd_show_policy_pos'] = $pwd_show_policy_pos;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_display_entropy'])) {
$custompwdfield['pwd_policy_config']['pwd_display_entropy'] = $pwd_display_entropy;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_check_entropy'])) {
$custompwdfield['pwd_policy_config']['pwd_check_entropy'] = $pwd_check_entropy;
}
if (!isset($custompwdfield['pwd_policy_config']['pwd_min_entropy'])) {
$custompwdfield['pwd_policy_config']['pwd_min_entropy'] = $pwd_min_entropy;
}
if (!isset($custompwdfield['who_change_password'])) {
$custompwdfield['who_change_password'] = $who_change_password;
}
if (!isset($custompwdfield['msg_changehelpextramessage'])) {
$custompwdfield['msg_changehelpextramessage'] = "";
}
if (!isset($custompwdfield['notify_on_change'])) {
$custompwdfield['notify_on_change'] = $notify_on_change;
}
if (!isset($custompwdfield['hash_options'])) {
$custompwdfield['hash_options'] = $hash_options;
}
if (!isset($custompwdfield['msg_passwordchangedextramessage'])) {
$custompwdfield['msg_passwordchangedextramessage'] = "";
}
if (!isset($custompwdfield['samba_mode'])) {
$custompwdfield['samba_mode'] = false;
}
if (!isset($custompwdfield['samba_options'])) {
$custompwdfield['samba_options'] = array();
}
if (!isset($custompwdfield['shadow_options'])) {
$custompwdfield['shadow_options'] = array();
}
if (!isset($custompwdfield['shadow_options']['update_shadowLastChange'])) {
$custompwdfield['sha$dow_options']['update_shadowLastChange'] = false;
}
if (!isset($custompwdfield['shadow_options']['update_shadowExpire'])) {
$custompwdfield['shadow_options']['update_shadowExpire'] = false;
}
if (!isset($custompwdfield['shadow_options']['shadow_expire_days'])) {
$custompwdfield['shadow_options']['shadow_expire_days'] = -1;

set_default_value($custompwdfield['ldap_use_ppolicy_control'], false);
set_default_value($custompwdfield['who_change_password'], $who_change_password);
set_default_value($custompwdfield['msg_changehelpextramessage'], "");
set_default_value($custompwdfield['notify_on_change'], $notify_on_change);
set_default_value($custompwdfield['hash_options'], $hash_options);
set_default_value($custompwdfield['msg_passwordchangedextramessage'], "");
set_default_value($custompwdfield['samba_mode'], false);
set_default_value($custompwdfield['samba_options'], array());
set_default_value($custompwdfield['shadow_options'], array());
set_default_value($custompwdfield['shadow_options']['update_shadowLastChange'], false);
set_default_value($custompwdfield['shadow_options']['update_shadowExpire'], false);
set_default_value($custompwdfield['shadow_options']['shadow_expire_days'], -1);
set_default_value($custompwdfield['pwd_policy_config'], array());
$default_pwd_policy_config = [
"pwd_show_policy" => $pwd_show_policy,
"pwd_min_length" => $pwd_min_length,
"pwd_max_length" => $pwd_max_length,
"pwd_min_lower" => $pwd_min_lower,
"pwd_min_upper" => $pwd_min_upper,
"pwd_min_digit" => $pwd_min_digit,
"pwd_min_special" => $pwd_min_special,
"pwd_special_chars" => $pwd_special_chars,
"pwd_forbidden_chars" => "",
"pwd_no_reuse" => $pwd_no_reuse,
"pwd_diff_last_min_chars" => $pwd_diff_last_min_chars,
"pwd_diff_login" => $pwd_diff_login,
"pwd_complexity" => $pwd_complexity,
"use_pwnedpasswords" => $use_pwnedpasswords,
"pwd_no_special_at_ends" => $pwd_no_special_at_ends,
"pwd_forbidden_words" => $pwd_forbidden_words,
"pwd_forbidden_ldap_fields" => $pwd_forbidden_ldap_fields,
"pwd_show_policy_pos" => $pwd_show_policy_pos,
"pwd_display_entropy" => $pwd_display_entropy,
"pwd_check_entropy" => $pwd_check_entropy,
"pwd_min_entropy" => $pwd_min_entropy,
"pwd_unique_across_custom_password_fields" => false
];
foreach ($default_pwd_policy_config as $param => $defaultValue) {
set_default_value($custompwdfield['pwd_policy_config'][$param], $defaultValue);
}

#==============================================================================
Expand Down Expand Up @@ -281,7 +229,7 @@
exec($command, $prehook_output, $prehook_return);
}
if ( ! isset($prehook_return) || $prehook_return === 0 || $custompwdfield['ignore_prehook_error'] ) {
$result = change_password($ldap, $userdn, $newcustompwd, false, array(), $custompwdfield['samba_mode'], $custompwdfield['samba_options'], $custompwdfield['shadow_options'], $custompwdfield['hash'], $custompwdfield['hash_options'], $custompwdfield['who_change_password'], $password, false, $custompwdfield['ldap_use_ppolicy_control'], true, $custompwdfield['attribute']);
$result = change_password($ldapInstance, $userdn, $newcustompwd, false, array(), $custompwdfield['samba_mode'], $custompwdfield['samba_options'], $custompwdfield['shadow_options'], $custompwdfield['hash'], $custompwdfield['hash_options'], $custompwdfield['who_change_password'], $password, false, $custompwdfield['ldap_use_ppolicy_control'], true, $custompwdfield['attribute']);
if ( $result === "passwordchanged" && isset($custompwdfield['posthook']) ) {
$command = hook_command($custompwdfield['posthook'], $login, $newcustompwd, $password, $custompwdfield['posthook_password_encodebase64']);
exec($command, $posthook_output, $posthook_return);
Expand Down Expand Up @@ -310,32 +258,33 @@
}

#==============================================================================
# Reuse config-variables and message-variables
# Overload config and message variables with the current custompwdfield config
#==============================================================================

$pwd_show_policy_pos = $custompwdfield['pwd_policy_config']['pwd_show_policy_pos'];
$pwd_show_policy = $custompwdfield['pwd_policy_config']['pwd_show_policy'];
$pwd_min_length = $custompwdfield['pwd_policy_config']['pwd_min_length'];
$pwd_max_length = $custompwdfield['pwd_policy_config']['pwd_max_length'];
$pwd_min_lower = $custompwdfield['pwd_policy_config']['pwd_min_lower'];
$pwd_min_upper = $custompwdfield['pwd_policy_config']['pwd_min_upper'];
$pwd_min_digit = $custompwdfield['pwd_policy_config']['pwd_min_digit'];
$pwd_min_special = $custompwdfield['pwd_policy_config']['pwd_min_special'];
$pwd_complexity = $custompwdfield['pwd_policy_config']['pwd_complexity'];
$pwd_show_policy_pos = $custompwdfield['pwd_policy_config']['pwd_show_policy_pos'];
$pwd_show_policy = $custompwdfield['pwd_policy_config']['pwd_show_policy'];
$pwd_min_length = $custompwdfield['pwd_policy_config']['pwd_min_length'];
$pwd_max_length = $custompwdfield['pwd_policy_config']['pwd_max_length'];
$pwd_min_lower = $custompwdfield['pwd_policy_config']['pwd_min_lower'];
$pwd_min_upper = $custompwdfield['pwd_policy_config']['pwd_min_upper'];
$pwd_min_digit = $custompwdfield['pwd_policy_config']['pwd_min_digit'];
$pwd_min_special = $custompwdfield['pwd_policy_config']['pwd_min_special'];
$pwd_complexity = $custompwdfield['pwd_policy_config']['pwd_complexity'];
$pwd_diff_last_min_chars = $custompwdfield['pwd_policy_config']['pwd_diff_last_min_chars'];
$pwd_forbidden_chars = $custompwdfield['pwd_policy_config']['pwd_forbidden_chars'];
$pwd_no_reuse = $custompwdfield['pwd_policy_config']['pwd_no_reuse'];
$pwd_diff_login = $custompwdfield['pwd_policy_config']['pwd_diff_login'];
$pwd_display_entropy = $custompwdfield['pwd_policy_config']['pwd_display_entropy'];
$pwd_check_entropy = $custompwdfield['pwd_policy_config']['pwd_check_entropy'];
$pwd_min_entropy = $custompwdfield['pwd_policy_config']['pwd_min_entropy'];
$use_pwnedpasswords = $custompwdfield['pwd_policy_config']['use_pwnedpasswords'];
$pwd_no_special_at_ends = $custompwdfield['pwd_policy_config']['pwd_no_special_at_ends'];
$pwd_forbidden_chars = $custompwdfield['pwd_policy_config']['pwd_forbidden_chars'];
$pwd_no_reuse = $custompwdfield['pwd_policy_config']['pwd_no_reuse'];
$pwd_diff_login = $custompwdfield['pwd_policy_config']['pwd_diff_login'];
$pwd_display_entropy = $custompwdfield['pwd_policy_config']['pwd_display_entropy'];
$pwd_check_entropy = $custompwdfield['pwd_policy_config']['pwd_check_entropy'];
$pwd_min_entropy = $custompwdfield['pwd_policy_config']['pwd_min_entropy'];
$use_pwnedpasswords = $custompwdfield['pwd_policy_config']['use_pwnedpasswords'];
$pwd_no_special_at_ends = $custompwdfield['pwd_policy_config']['pwd_no_special_at_ends'];

$messages['sameasold'] = $messages['sameasaccountpassword'];
$messages['policynoreuse'] = $messages['policynoreusecustompwdfield'];
if (!isset($custompwdfield['label'])) {
$messages['newcustompassword'] = $messages['changehelpcustompwdfield']."custom password"; # default generic label
# default generic label
$messages['newcustompassword'] = $messages['changehelpcustompwdfield']."custom password";
} else {
$messages['newcustompassword'] = $messages['changehelpcustompwdfield'].$custompwdfield['label'];
}
Loading

0 comments on commit e458c7e

Please sign in to comment.