diff --git a/Dockerfile b/Dockerfile index 353be30..34a25ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,8 @@ # Please check https://www\.multiOTP.net/ and you will find the magic button ;-) # # @author Andre Liechti, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2013-11-29 # @copyright (c) 2013-2022 SysCo systemes de communication sa # @copyright GNU Lesser General Public License @@ -46,7 +46,7 @@ MAINTAINER Andre Liechti LABEL Description="multiOTP open source, running on Debian ${DEBIAN} with PHP${PHPVERSION}." \ License="LGPL-3.0" \ Usage="docker run -v [PATH/TO/MULTIOTP/DATA/VOLUME]:/etc/multiotp -v [PATH/TO/FREERADIUS/CONFIG/VOLUME]:/etc/freeradius -v [PATH/TO/MULTIOTP/LOG/VOLUME]:/var/log/multiotp -v [PATH/TO/FREERADIUS/LOG/VOLUME]:/var/log/freeradius -p [HOST WWW PORT NUMBER]:80 -p [HOST SSL PORT NUMBER]:443 -p [HOST RADIUS-AUTH PORT NUMBER]:1812/udp -p [HOST RADIUS-ACCNT PORT NUMBER]:1813/udp -d multiotp-open-source" \ - Version="5.9.4.0" + Version="5.9.5.0" ARG DEBIAN_FRONTEND=noninteractive diff --git a/README.md b/README.md index d4ca821..8182ec3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ multiOTP open source is OATH certified for HOTP/TOTP (c) 2010-2022 SysCo systemes de communication sa https://www.multiotp.net/ -Current build: 5.9.4.0 (2022-11-04) +Current build: 5.9.5.0 (2022-11-11) Binary download: https://download.multiotp.net/ (including virtual appliance image) @@ -152,6 +152,7 @@ WHAT'S NEW IN THIS 5.9.x RELEASE CHANGE LOG OF RELEASED VERSIONS =============================== ``` +2022-11-11 5.9.5.0 ENH: It's now possible to define a special AD/LDAP group to attribute "Without2FA" token to specific users 2022-11-04 5.9.4.0 ENH: Enhanced multiOTP Credential Provider 2022-10-21 5.9.3.1 FIX: Better special characters support in username and password ENH: The locked accounts list now also list the temporary delayed accounts @@ -1556,7 +1557,7 @@ MULTIOTP COMMAND LINE TOOL ========================== ``` -multiOTP 5.9.4.0 (2022-11-04) +multiOTP 5.9.5.0 (2022-11-11) (c) 2010-2022 SysCo systemes de communication sa http://www.multiOTP.net (you can try the [Donate] button ;-) @@ -1771,6 +1772,7 @@ Usage: ldap-time-limit: LDAP/AD number of sec. to wait for search results ldap-users-dn: LDAP/AD users DN (optional, use base-dn if empty) (you can put several DN separated by semicolons) + ldap-without2fa-in-group: Special LDAP/AD group(s) for without2fa users ldaptls_reqcert: ['auto'|'never'|''|...] how to perform the LDAP TLS server certificate checks (LDAPTLS_REQCERT) 'auto' means 'never' for Windows and '' for Linux @@ -2070,8 +2072,8 @@ Visit https://forum.multiotp.net/ for additional support ``` ``` -Hash verification for multiotp_5.9.4.0.zip -SHA256:2b227098d6b2980dd29f7deb372434916936eae1f7d91b45b309cf5911201470 -SHA1:9dd0246a4764ab5bf9c837ebe16be3c3b7d1609e -MD5:e52beba7ea09cf688ba68833ccfd6b71 +Hash verification for multiotp_5.9.5.0.zip +SHA256:ec8e92d38d236b3ddbf1ae5d7e5286656fd7457960204e4e74ef2bcd6089f6ae +SHA1:ff298f47886abbdf55a9a366a82b4b800a39978d +MD5:7ccf347a26f8fc83e5634bffe827256e ``` diff --git a/check.multiotp.class.php b/check.multiotp.class.php index 001feb9..eb1ba11 100644 --- a/check.multiotp.class.php +++ b/check.multiotp.class.php @@ -22,8 +22,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2013-07-10 * @copyright (c) 2013-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License diff --git a/checkmultiotp.cmd b/checkmultiotp.cmd index 6a875de..11b7ed8 100644 --- a/checkmultiotp.cmd +++ b/checkmultiotp.cmd @@ -11,8 +11,8 @@ REM REM Windows batch file for Windows 2K/XP/2003/7/2008/8/2012/10/2019 REM REM @author Andre Liechti, SysCo systemes de communication sa, -REM @version 5.9.4.0 -REM @date 2022-11-04 +REM @version 5.9.5.0 +REM @date 2022-11-11 REM @since 2010-07-10 REM @copyright (c) 2010-2022 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License diff --git a/launcher/ReadMe.txt b/launcher/ReadMe.txt index fe6695f..9dfecbc 100644 --- a/launcher/ReadMe.txt +++ b/launcher/ReadMe.txt @@ -15,8 +15,8 @@ The multiOTP C++ launcher is simply used to launch PHP and run multiotp.windows.php with the provided arguments. @author Andre Liechti, SysCo systemes de communication sa, -@version 5.9.4.0 -@date 2022-11-04 +@version 5.9.5.0 +@date 2022-11-11 @since 2016-12-08 @copyright (c) 2010-2022 SysCo systemes de communication sa @copyright GNU Lesser General Public License diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp index 2ca2472..f55e0c5 100644 --- a/launcher/launcher.cpp +++ b/launcher/launcher.cpp @@ -14,8 +14,8 @@ * and run multiotp.windows.php with the provided arguments. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2016-12-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -68,8 +68,8 @@ #include #define SOFTWARE "LAUNCHPHPMULTIOTP" -#define VER_NUMBER "5.9.4.0" -#define VER_DATE "2022-11-04" +#define VER_NUMBER "5.9.5.0" +#define VER_DATE "2022-11-11" void replaceAll(std::string& str, const std::string& from, const std::string& to) { if (from.empty()) diff --git a/multiotp.class.php b/multiotp.class.php index d95e8cb..aef4ee1 100644 --- a/multiotp.class.php +++ b/multiotp.class.php @@ -72,8 +72,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -277,8 +277,8 @@ class Multiotp * @brief Main class definition of the multiOTP project. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ { @@ -376,8 +376,8 @@ class Multiotp * @retval void * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ function __construct( @@ -401,11 +401,11 @@ function __construct( if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { - $temp_version = '@version 5.9.4.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) + $temp_version = '@version 5.9.5.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) $this->_version = trim(mb_substr($temp_version, 8)); } if (!isset($this->_date)) { - $temp_date = '@date 2022-11-04'; // You should update the date with the date of your changes + $temp_date = '@date 2022-11-11'; // You should update the date with the date of your changes $this->_date = trim(mb_substr($temp_date, 8)); } if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMiBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } @@ -589,6 +589,7 @@ function __construct( 'ldap_ssl' => "int(1) DEFAULT 0", 'ldap_synced_user_attribute' => "TEXT DEFAULT ''", 'ldap_time_limit' => "int(10) DEFAULT 30", + 'ldap_without2fa_in_group' => "TEXT DEFAULT ''", // If ldaptls_reqcert is empty, the default value used is "auto" 'ldaptls_reqcert' => "TEXT DEFAULT ''", // If ldaptls_cipher_suite is empty, the default value used is "auto" @@ -6754,7 +6755,7 @@ function GetLdapSecondaryController() function SetLdapInGroup( $value ) { - $this->_config_data['ldap_in_group'] = $value; + $this->_config_data['ldap_in_group'] = trim($value); $ldap_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); @@ -6778,9 +6779,46 @@ function SetLdapInGroup( } - function GetLdapInGroup() + function GetLdapInGroup($included_without2fa = false) { - return $this->_config_data['ldap_in_group']; + $groups = trim($this->_config_data['ldap_in_group']); + if ((true === $included_without2fa) && ('' != $groups) && ('' != $this->GetLdapWithout2faInGroup())) { + $groups = $this->GetLdapWithout2faInGroup() . "," . $groups; + } + return $groups; + } + + + function SetLdapWithout2faInGroup( + $value + ) { + $this->_config_data['ldap_without2fa_in_group'] = trim($value); + + $ldap_without2fa_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + + $groups_array = array(); + $list = explode("\t", $this->GetGroupsList()); + $n = count($list); + for($i = 0; $i < $n; $i++) { + if($list[$i] != '') { + $this->SetGroup($list[$i]); + $groups_array[] = $this->GetGroupName(); + } + } + + foreach ($ldap_without2fa_in_group_array as $one_group) { + if (!in_array(trim($one_group), $groups_array)) { + if ('' != trim($one_group)) { + $this->CreateGroup('', trim($one_group), trim($one_group)); + } + } + } + } + + + function GetLdapWithout2faInGroup() + { + return $this->_config_data['ldap_without2fa_in_group']; } @@ -13836,8 +13874,8 @@ function GetLdapUsersList( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -13933,7 +13971,7 @@ function GetLdapUsersList( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14026,7 +14064,7 @@ function GetLdapUsersList( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14198,8 +14236,8 @@ function GetLdapUsersInfoArray( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14294,7 +14332,7 @@ function GetLdapUsersInfoArray( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if (2 == $this->GetLdapServerType()) { // Generic LDAP, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14387,7 +14425,7 @@ function GetLdapUsersInfoArray( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14688,8 +14726,8 @@ function SyncLdapUsers( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14840,7 +14878,7 @@ function SyncLdapUsers( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { @@ -14969,7 +15007,7 @@ function SyncLdapUsers( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -15135,16 +15173,31 @@ function SyncLdapUsers( } $ldap_framedipnetmask = (isset($one_user['radiusframedipnetmask'][0]) ? ($one_user['radiusframedipnetmask'][0]) : "---"); + $ldap_algorithm = $this->GetLdapDefaultAlgorithm(); + if ('' != trim($this->GetLdapWithout2faInGroup())) { + $without2fa_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapWithout2faInGroup())))); + $user_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$user_in_groups)))); + foreach ($without2fa_in_groups_array_raw as $one_without2fa_group) { + foreach ($user_in_groups_array_raw as $one_temp) { + if (strtolower($one_without2fa_group) == strtolower($one_temp)) { + $ldap_algorithm = "without2fa"; + break; + } + } + } + } + if (!$this->CheckUserExists($account, true, true)) { // $no_server_check = TRUE; $no_error = TRUE // User doesn't exist yet if ('' == $ldap_description) { $ldap_description = $account; } + $result = $this->FastCreateUser($account, $ldap_email, $ldap_sms, -1, // Prefix pin needed - $this->GetLdapDefaultAlgorithm(), + $ldap_algorithm, $ldap_enabled, $ldap_description, $ldap_group, @@ -15167,6 +15220,7 @@ function SyncLdapUsers( $existing_ldap_users_counter++; $this->SetUser($account); if (1 == $this->GetUserSynchronized()) { + $algorithm = $this->GetUserAlgorithm(); $description = $this->GetUserDescription(); $display_name = $this->GetUserDisplayName(); $email = $this->GetUserEmail(); @@ -15182,6 +15236,15 @@ function SyncLdapUsers( $modified = FALSE; $detailed_modif = ""; + // !!! Special without2fa behavior !!! + if ((('without2fa' == $ldap_algorithm) && ($algorithm != $ldap_algorithm)) || + (('without2fa' != $ldap_algorithm) && ('without2fa' == $algorithm) && ('' != trim($this->GetLdapWithout2faInGroup()))) + ) { + $this->SetUserAlgorithm($ldap_algorithm); + $modified = TRUE; + $detailed_modif = (('' != $detailed_modif) ? ', ' : '') . "Algorithm: $algorithm -> $ldap_algorithm"; + } + if (('' != $ldap_description) && ($description != $ldap_description)) { $this->SetUserDescription($ldap_description); $modified = TRUE; diff --git a/multiotp.cli.header.php b/multiotp.cli.header.php index 782b22d..774f4e8 100644 --- a/multiotp.cli.header.php +++ b/multiotp.cli.header.php @@ -35,8 +35,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -1602,6 +1602,10 @@ function clean_quotes( $multiotp->SetLdapUsersDn($actual_array[1]); $write_config_data = true; break; + case 'ldap-without2fa-in-group': + $multiotp->SetLdapWithout2faInGroup($actual_array[1]); + $write_config_data = true; + break; case 'log': $multiotp->SetLogOption(intval($actual_array[1])); $write_config_data = true; @@ -2304,6 +2308,7 @@ function clean_quotes( echo " ldap-time-limit: LDAP/AD number of sec. to wait for search results".$crlf; echo " ldap-users-dn: LDAP/AD users DN (optional, use base-dn if empty)".$crlf; echo " (you can put several DN separated by semicolons)".$crlf; + echo " ldap-without2fa-in-group: Special LDAP/AD group(s) for without2fa users".$crlf; echo " ldaptls_reqcert: ['auto'|'never'|''|...] how to perform the LDAP TLS".$crlf; echo " server certificate checks (LDAPTLS_REQCERT)".$crlf; echo " 'auto' means 'never' for Windows and '' for Linux".$crlf; diff --git a/multiotp.cli.proxy.php b/multiotp.cli.proxy.php index e000019..e205780 100644 --- a/multiotp.cli.proxy.php +++ b/multiotp.cli.proxy.php @@ -15,8 +15,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License diff --git a/multiotp.php b/multiotp.php index e9b4d29..b9d1008 100644 --- a/multiotp.php +++ b/multiotp.php @@ -37,8 +37,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -277,8 +277,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -482,8 +482,8 @@ class Multiotp * @brief Main class definition of the multiOTP project. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ { @@ -581,8 +581,8 @@ class Multiotp * @retval void * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ function __construct( @@ -606,11 +606,11 @@ function __construct( if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { - $temp_version = '@version 5.9.4.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) + $temp_version = '@version 5.9.5.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) $this->_version = trim(mb_substr($temp_version, 8)); } if (!isset($this->_date)) { - $temp_date = '@date 2022-11-04'; // You should update the date with the date of your changes + $temp_date = '@date 2022-11-11'; // You should update the date with the date of your changes $this->_date = trim(mb_substr($temp_date, 8)); } if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMiBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } @@ -794,6 +794,7 @@ function __construct( 'ldap_ssl' => "int(1) DEFAULT 0", 'ldap_synced_user_attribute' => "TEXT DEFAULT ''", 'ldap_time_limit' => "int(10) DEFAULT 30", + 'ldap_without2fa_in_group' => "TEXT DEFAULT ''", // If ldaptls_reqcert is empty, the default value used is "auto" 'ldaptls_reqcert' => "TEXT DEFAULT ''", // If ldaptls_cipher_suite is empty, the default value used is "auto" @@ -6959,7 +6960,7 @@ function GetLdapSecondaryController() function SetLdapInGroup( $value ) { - $this->_config_data['ldap_in_group'] = $value; + $this->_config_data['ldap_in_group'] = trim($value); $ldap_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); @@ -6983,9 +6984,46 @@ function SetLdapInGroup( } - function GetLdapInGroup() + function GetLdapInGroup($included_without2fa = false) { - return $this->_config_data['ldap_in_group']; + $groups = trim($this->_config_data['ldap_in_group']); + if ((true === $included_without2fa) && ('' != $groups) && ('' != $this->GetLdapWithout2faInGroup())) { + $groups = $this->GetLdapWithout2faInGroup() . "," . $groups; + } + return $groups; + } + + + function SetLdapWithout2faInGroup( + $value + ) { + $this->_config_data['ldap_without2fa_in_group'] = trim($value); + + $ldap_without2fa_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + + $groups_array = array(); + $list = explode("\t", $this->GetGroupsList()); + $n = count($list); + for($i = 0; $i < $n; $i++) { + if($list[$i] != '') { + $this->SetGroup($list[$i]); + $groups_array[] = $this->GetGroupName(); + } + } + + foreach ($ldap_without2fa_in_group_array as $one_group) { + if (!in_array(trim($one_group), $groups_array)) { + if ('' != trim($one_group)) { + $this->CreateGroup('', trim($one_group), trim($one_group)); + } + } + } + } + + + function GetLdapWithout2faInGroup() + { + return $this->_config_data['ldap_without2fa_in_group']; } @@ -14041,8 +14079,8 @@ function GetLdapUsersList( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14138,7 +14176,7 @@ function GetLdapUsersList( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14231,7 +14269,7 @@ function GetLdapUsersList( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14403,8 +14441,8 @@ function GetLdapUsersInfoArray( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14499,7 +14537,7 @@ function GetLdapUsersInfoArray( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if (2 == $this->GetLdapServerType()) { // Generic LDAP, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14592,7 +14630,7 @@ function GetLdapUsersInfoArray( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14893,8 +14931,8 @@ function SyncLdapUsers( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -15045,7 +15083,7 @@ function SyncLdapUsers( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { @@ -15174,7 +15212,7 @@ function SyncLdapUsers( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -15340,16 +15378,31 @@ function SyncLdapUsers( } $ldap_framedipnetmask = (isset($one_user['radiusframedipnetmask'][0]) ? ($one_user['radiusframedipnetmask'][0]) : "---"); + $ldap_algorithm = $this->GetLdapDefaultAlgorithm(); + if ('' != trim($this->GetLdapWithout2faInGroup())) { + $without2fa_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapWithout2faInGroup())))); + $user_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$user_in_groups)))); + foreach ($without2fa_in_groups_array_raw as $one_without2fa_group) { + foreach ($user_in_groups_array_raw as $one_temp) { + if (strtolower($one_without2fa_group) == strtolower($one_temp)) { + $ldap_algorithm = "without2fa"; + break; + } + } + } + } + if (!$this->CheckUserExists($account, true, true)) { // $no_server_check = TRUE; $no_error = TRUE // User doesn't exist yet if ('' == $ldap_description) { $ldap_description = $account; } + $result = $this->FastCreateUser($account, $ldap_email, $ldap_sms, -1, // Prefix pin needed - $this->GetLdapDefaultAlgorithm(), + $ldap_algorithm, $ldap_enabled, $ldap_description, $ldap_group, @@ -15372,6 +15425,7 @@ function SyncLdapUsers( $existing_ldap_users_counter++; $this->SetUser($account); if (1 == $this->GetUserSynchronized()) { + $algorithm = $this->GetUserAlgorithm(); $description = $this->GetUserDescription(); $display_name = $this->GetUserDisplayName(); $email = $this->GetUserEmail(); @@ -15387,6 +15441,15 @@ function SyncLdapUsers( $modified = FALSE; $detailed_modif = ""; + // !!! Special without2fa behavior !!! + if ((('without2fa' == $ldap_algorithm) && ($algorithm != $ldap_algorithm)) || + (('without2fa' != $ldap_algorithm) && ('without2fa' == $algorithm) && ('' != trim($this->GetLdapWithout2faInGroup()))) + ) { + $this->SetUserAlgorithm($ldap_algorithm); + $modified = TRUE; + $detailed_modif = (('' != $detailed_modif) ? ', ' : '') . "Algorithm: $algorithm -> $ldap_algorithm"; + } + if (('' != $ldap_description) && ($description != $ldap_description)) { $this->SetUserDescription($ldap_description); $modified = TRUE; @@ -75164,6 +75227,10 @@ function clean_quotes( $multiotp->SetLdapUsersDn($actual_array[1]); $write_config_data = true; break; + case 'ldap-without2fa-in-group': + $multiotp->SetLdapWithout2faInGroup($actual_array[1]); + $write_config_data = true; + break; case 'log': $multiotp->SetLogOption(intval($actual_array[1])); $write_config_data = true; @@ -75866,6 +75933,7 @@ function clean_quotes( echo " ldap-time-limit: LDAP/AD number of sec. to wait for search results".$crlf; echo " ldap-users-dn: LDAP/AD users DN (optional, use base-dn if empty)".$crlf; echo " (you can put several DN separated by semicolons)".$crlf; + echo " ldap-without2fa-in-group: Special LDAP/AD group(s) for without2fa users".$crlf; echo " ldaptls_reqcert: ['auto'|'never'|''|...] how to perform the LDAP TLS".$crlf; echo " server certificate checks (LDAPTLS_REQCERT)".$crlf; echo " 'auto' means 'never' for Windows and '' for Linux".$crlf; diff --git a/multiotp.server.php b/multiotp.server.php index d404f59..71923c2 100644 --- a/multiotp.server.php +++ b/multiotp.server.php @@ -27,8 +27,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2013-08-06 * @copyright (c) 2013-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License diff --git a/radius_debug.cmd b/radius_debug.cmd index 2c7e374..ee0c4b9 100644 --- a/radius_debug.cmd +++ b/radius_debug.cmd @@ -9,8 +9,8 @@ REM REM Windows batch file for Windows 2K/XP/2003/7/2008/8/2012/10 REM REM @author Andre Liechti, SysCo systemes de communication sa, -REM @version 5.9.4.0 -REM @date 2022-11-04 +REM @version 5.9.5.0 +REM @date 2022-11-11 REM @since 2014-04-22 REM @copyright (c) 2014-2022 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License diff --git a/radius_install.cmd b/radius_install.cmd index 320af7e..e3138d6 100644 --- a/radius_install.cmd +++ b/radius_install.cmd @@ -9,8 +9,8 @@ REM REM Windows batch file for Windows 2K/XP/2003/7/2008/8/2012/10 REM REM @author Andre Liechti, SysCo systemes de communication sa, -REM @version 5.9.4.0 -REM @date 2022-11-04 +REM @version 5.9.5.0 +REM @date 2022-11-11 REM @since 2013-08-20 REM @copyright (c) 2013-2022 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License diff --git a/radius_uninstall.cmd b/radius_uninstall.cmd index 9311a8d..35461d0 100644 --- a/radius_uninstall.cmd +++ b/radius_uninstall.cmd @@ -9,8 +9,8 @@ REM REM Windows batch file for Windows 2K/XP/2003/7/2008/8/2012/10 REM REM @author Andre Liechti, SysCo systemes de communication sa, -REM @version 5.9.4.0 -REM @date 2022-11-04 +REM @version 5.9.5.0 +REM @date 2022-11-11 REM @since 2013-08-20 REM @copyright (c) 2013-2022 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License diff --git a/raspberry/boot-part/install.sh b/raspberry/boot-part/install.sh index e6b7866..8cf79bc 100644 --- a/raspberry/boot-part/install.sh +++ b/raspberry/boot-part/install.sh @@ -16,8 +16,8 @@ # Please check https://www.multiotp.net/ and you will find the magic button ;-) # # @author Andre Liechti, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2013-11-29 # @copyright (c) 2013-2022 by SysCo systemes de communication sa # @copyright GNU Lesser General Public License @@ -69,7 +69,7 @@ SSH_ROOT_LOGIN="1" DEFAULT_IP="192.168.1.44" REBOOT_AT_THE_END="1" -TEMPVERSION="@version 5.9.4.0" +TEMPVERSION="@version 5.9.5.0" MULTIOTPVERSION="$(echo -e "${TEMPVERSION:8}" | tr -d '[[:space:]]')" IFS='.' read -ra MULTIOTPVERSIONARRAY <<< "$MULTIOTPVERSION" MULTIOTPMAJORVERSION=${MULTIOTPVERSIONARRAY[0]} diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/index.php b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/index.php index 82895e1..fdea09a 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/index.php +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/index.php @@ -27,8 +27,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2013-08-06 * @copyright (c) 2013-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -192,8 +192,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -397,8 +397,8 @@ class Multiotp * @brief Main class definition of the multiOTP project. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ { @@ -496,8 +496,8 @@ class Multiotp * @retval void * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ function __construct( @@ -521,11 +521,11 @@ function __construct( if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { - $temp_version = '@version 5.9.4.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) + $temp_version = '@version 5.9.5.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) $this->_version = trim(mb_substr($temp_version, 8)); } if (!isset($this->_date)) { - $temp_date = '@date 2022-11-04'; // You should update the date with the date of your changes + $temp_date = '@date 2022-11-11'; // You should update the date with the date of your changes $this->_date = trim(mb_substr($temp_date, 8)); } if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMiBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } @@ -709,6 +709,7 @@ function __construct( 'ldap_ssl' => "int(1) DEFAULT 0", 'ldap_synced_user_attribute' => "TEXT DEFAULT ''", 'ldap_time_limit' => "int(10) DEFAULT 30", + 'ldap_without2fa_in_group' => "TEXT DEFAULT ''", // If ldaptls_reqcert is empty, the default value used is "auto" 'ldaptls_reqcert' => "TEXT DEFAULT ''", // If ldaptls_cipher_suite is empty, the default value used is "auto" @@ -6874,7 +6875,7 @@ function GetLdapSecondaryController() function SetLdapInGroup( $value ) { - $this->_config_data['ldap_in_group'] = $value; + $this->_config_data['ldap_in_group'] = trim($value); $ldap_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); @@ -6898,9 +6899,46 @@ function SetLdapInGroup( } - function GetLdapInGroup() + function GetLdapInGroup($included_without2fa = false) { - return $this->_config_data['ldap_in_group']; + $groups = trim($this->_config_data['ldap_in_group']); + if ((true === $included_without2fa) && ('' != $groups) && ('' != $this->GetLdapWithout2faInGroup())) { + $groups = $this->GetLdapWithout2faInGroup() . "," . $groups; + } + return $groups; + } + + + function SetLdapWithout2faInGroup( + $value + ) { + $this->_config_data['ldap_without2fa_in_group'] = trim($value); + + $ldap_without2fa_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + + $groups_array = array(); + $list = explode("\t", $this->GetGroupsList()); + $n = count($list); + for($i = 0; $i < $n; $i++) { + if($list[$i] != '') { + $this->SetGroup($list[$i]); + $groups_array[] = $this->GetGroupName(); + } + } + + foreach ($ldap_without2fa_in_group_array as $one_group) { + if (!in_array(trim($one_group), $groups_array)) { + if ('' != trim($one_group)) { + $this->CreateGroup('', trim($one_group), trim($one_group)); + } + } + } + } + + + function GetLdapWithout2faInGroup() + { + return $this->_config_data['ldap_without2fa_in_group']; } @@ -13956,8 +13994,8 @@ function GetLdapUsersList( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14053,7 +14091,7 @@ function GetLdapUsersList( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14146,7 +14184,7 @@ function GetLdapUsersList( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14318,8 +14356,8 @@ function GetLdapUsersInfoArray( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14414,7 +14452,7 @@ function GetLdapUsersInfoArray( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if (2 == $this->GetLdapServerType()) { // Generic LDAP, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14507,7 +14545,7 @@ function GetLdapUsersInfoArray( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14808,8 +14846,8 @@ function SyncLdapUsers( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14960,7 +14998,7 @@ function SyncLdapUsers( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { @@ -15089,7 +15127,7 @@ function SyncLdapUsers( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -15255,16 +15293,31 @@ function SyncLdapUsers( } $ldap_framedipnetmask = (isset($one_user['radiusframedipnetmask'][0]) ? ($one_user['radiusframedipnetmask'][0]) : "---"); + $ldap_algorithm = $this->GetLdapDefaultAlgorithm(); + if ('' != trim($this->GetLdapWithout2faInGroup())) { + $without2fa_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapWithout2faInGroup())))); + $user_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$user_in_groups)))); + foreach ($without2fa_in_groups_array_raw as $one_without2fa_group) { + foreach ($user_in_groups_array_raw as $one_temp) { + if (strtolower($one_without2fa_group) == strtolower($one_temp)) { + $ldap_algorithm = "without2fa"; + break; + } + } + } + } + if (!$this->CheckUserExists($account, true, true)) { // $no_server_check = TRUE; $no_error = TRUE // User doesn't exist yet if ('' == $ldap_description) { $ldap_description = $account; } + $result = $this->FastCreateUser($account, $ldap_email, $ldap_sms, -1, // Prefix pin needed - $this->GetLdapDefaultAlgorithm(), + $ldap_algorithm, $ldap_enabled, $ldap_description, $ldap_group, @@ -15287,6 +15340,7 @@ function SyncLdapUsers( $existing_ldap_users_counter++; $this->SetUser($account); if (1 == $this->GetUserSynchronized()) { + $algorithm = $this->GetUserAlgorithm(); $description = $this->GetUserDescription(); $display_name = $this->GetUserDisplayName(); $email = $this->GetUserEmail(); @@ -15302,6 +15356,15 @@ function SyncLdapUsers( $modified = FALSE; $detailed_modif = ""; + // !!! Special without2fa behavior !!! + if ((('without2fa' == $ldap_algorithm) && ($algorithm != $ldap_algorithm)) || + (('without2fa' != $ldap_algorithm) && ('without2fa' == $algorithm) && ('' != trim($this->GetLdapWithout2faInGroup()))) + ) { + $this->SetUserAlgorithm($ldap_algorithm); + $modified = TRUE; + $detailed_modif = (('' != $detailed_modif) ? ', ' : '') . "Algorithm: $algorithm -> $ldap_algorithm"; + } + if (('' != $ldap_description) && ($description != $ldap_description)) { $this->SetUserDescription($ldap_description); $modified = TRUE; diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.class.php b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.class.php index 412612b..df54234 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.class.php +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.class.php @@ -72,8 +72,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -277,8 +277,8 @@ class Multiotp * @brief Main class definition of the multiOTP project. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ { @@ -376,8 +376,8 @@ class Multiotp * @retval void * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ function __construct( @@ -401,11 +401,11 @@ function __construct( if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { - $temp_version = '@version 5.9.4.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) + $temp_version = '@version 5.9.5.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) $this->_version = trim(mb_substr($temp_version, 8)); } if (!isset($this->_date)) { - $temp_date = '@date 2022-11-04'; // You should update the date with the date of your changes + $temp_date = '@date 2022-11-11'; // You should update the date with the date of your changes $this->_date = trim(mb_substr($temp_date, 8)); } if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMiBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } @@ -589,6 +589,7 @@ function __construct( 'ldap_ssl' => "int(1) DEFAULT 0", 'ldap_synced_user_attribute' => "TEXT DEFAULT ''", 'ldap_time_limit' => "int(10) DEFAULT 30", + 'ldap_without2fa_in_group' => "TEXT DEFAULT ''", // If ldaptls_reqcert is empty, the default value used is "auto" 'ldaptls_reqcert' => "TEXT DEFAULT ''", // If ldaptls_cipher_suite is empty, the default value used is "auto" @@ -6754,7 +6755,7 @@ function GetLdapSecondaryController() function SetLdapInGroup( $value ) { - $this->_config_data['ldap_in_group'] = $value; + $this->_config_data['ldap_in_group'] = trim($value); $ldap_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); @@ -6778,9 +6779,46 @@ function SetLdapInGroup( } - function GetLdapInGroup() + function GetLdapInGroup($included_without2fa = false) { - return $this->_config_data['ldap_in_group']; + $groups = trim($this->_config_data['ldap_in_group']); + if ((true === $included_without2fa) && ('' != $groups) && ('' != $this->GetLdapWithout2faInGroup())) { + $groups = $this->GetLdapWithout2faInGroup() . "," . $groups; + } + return $groups; + } + + + function SetLdapWithout2faInGroup( + $value + ) { + $this->_config_data['ldap_without2fa_in_group'] = trim($value); + + $ldap_without2fa_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + + $groups_array = array(); + $list = explode("\t", $this->GetGroupsList()); + $n = count($list); + for($i = 0; $i < $n; $i++) { + if($list[$i] != '') { + $this->SetGroup($list[$i]); + $groups_array[] = $this->GetGroupName(); + } + } + + foreach ($ldap_without2fa_in_group_array as $one_group) { + if (!in_array(trim($one_group), $groups_array)) { + if ('' != trim($one_group)) { + $this->CreateGroup('', trim($one_group), trim($one_group)); + } + } + } + } + + + function GetLdapWithout2faInGroup() + { + return $this->_config_data['ldap_without2fa_in_group']; } @@ -13836,8 +13874,8 @@ function GetLdapUsersList( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -13933,7 +13971,7 @@ function GetLdapUsersList( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14026,7 +14064,7 @@ function GetLdapUsersList( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14198,8 +14236,8 @@ function GetLdapUsersInfoArray( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14294,7 +14332,7 @@ function GetLdapUsersInfoArray( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if (2 == $this->GetLdapServerType()) { // Generic LDAP, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14387,7 +14425,7 @@ function GetLdapUsersInfoArray( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14688,8 +14726,8 @@ function SyncLdapUsers( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14840,7 +14878,7 @@ function SyncLdapUsers( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { @@ -14969,7 +15007,7 @@ function SyncLdapUsers( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -15135,16 +15173,31 @@ function SyncLdapUsers( } $ldap_framedipnetmask = (isset($one_user['radiusframedipnetmask'][0]) ? ($one_user['radiusframedipnetmask'][0]) : "---"); + $ldap_algorithm = $this->GetLdapDefaultAlgorithm(); + if ('' != trim($this->GetLdapWithout2faInGroup())) { + $without2fa_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapWithout2faInGroup())))); + $user_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$user_in_groups)))); + foreach ($without2fa_in_groups_array_raw as $one_without2fa_group) { + foreach ($user_in_groups_array_raw as $one_temp) { + if (strtolower($one_without2fa_group) == strtolower($one_temp)) { + $ldap_algorithm = "without2fa"; + break; + } + } + } + } + if (!$this->CheckUserExists($account, true, true)) { // $no_server_check = TRUE; $no_error = TRUE // User doesn't exist yet if ('' == $ldap_description) { $ldap_description = $account; } + $result = $this->FastCreateUser($account, $ldap_email, $ldap_sms, -1, // Prefix pin needed - $this->GetLdapDefaultAlgorithm(), + $ldap_algorithm, $ldap_enabled, $ldap_description, $ldap_group, @@ -15167,6 +15220,7 @@ function SyncLdapUsers( $existing_ldap_users_counter++; $this->SetUser($account); if (1 == $this->GetUserSynchronized()) { + $algorithm = $this->GetUserAlgorithm(); $description = $this->GetUserDescription(); $display_name = $this->GetUserDisplayName(); $email = $this->GetUserEmail(); @@ -15182,6 +15236,15 @@ function SyncLdapUsers( $modified = FALSE; $detailed_modif = ""; + // !!! Special without2fa behavior !!! + if ((('without2fa' == $ldap_algorithm) && ($algorithm != $ldap_algorithm)) || + (('without2fa' != $ldap_algorithm) && ('without2fa' == $algorithm) && ('' != trim($this->GetLdapWithout2faInGroup()))) + ) { + $this->SetUserAlgorithm($ldap_algorithm); + $modified = TRUE; + $detailed_modif = (('' != $detailed_modif) ? ', ' : '') . "Algorithm: $algorithm -> $ldap_algorithm"; + } + if (('' != $ldap_description) && ($description != $ldap_description)) { $this->SetUserDescription($ldap_description); $modified = TRUE; diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.php b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.php index 908d76d..df51aae 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.php +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.php @@ -17,8 +17,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.proxy.php b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.proxy.php index ea4619c..31f4193 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.proxy.php +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/multiotp.proxy.php @@ -36,8 +36,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -276,8 +276,8 @@ * PHP 5.3.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-06-08 * @copyright (c) 2010-2022 SysCo systemes de communication sa * @copyright GNU Lesser General Public License @@ -481,8 +481,8 @@ class Multiotp * @brief Main class definition of the multiOTP project. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ { @@ -580,8 +580,8 @@ class Multiotp * @retval void * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.4.0 - * @date 2022-11-04 + * @version 5.9.5.0 + * @date 2022-11-11 * @since 2010-07-18 */ function __construct( @@ -605,11 +605,11 @@ function __construct( if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { - $temp_version = '@version 5.9.4.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) + $temp_version = '@version 5.9.5.0'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) $this->_version = trim(mb_substr($temp_version, 8)); } if (!isset($this->_date)) { - $temp_date = '@date 2022-11-04'; // You should update the date with the date of your changes + $temp_date = '@date 2022-11-11'; // You should update the date with the date of your changes $this->_date = trim(mb_substr($temp_date, 8)); } if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMiBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } @@ -793,6 +793,7 @@ function __construct( 'ldap_ssl' => "int(1) DEFAULT 0", 'ldap_synced_user_attribute' => "TEXT DEFAULT ''", 'ldap_time_limit' => "int(10) DEFAULT 30", + 'ldap_without2fa_in_group' => "TEXT DEFAULT ''", // If ldaptls_reqcert is empty, the default value used is "auto" 'ldaptls_reqcert' => "TEXT DEFAULT ''", // If ldaptls_cipher_suite is empty, the default value used is "auto" @@ -6958,7 +6959,7 @@ function GetLdapSecondaryController() function SetLdapInGroup( $value ) { - $this->_config_data['ldap_in_group'] = $value; + $this->_config_data['ldap_in_group'] = trim($value); $ldap_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); @@ -6982,9 +6983,46 @@ function SetLdapInGroup( } - function GetLdapInGroup() + function GetLdapInGroup($included_without2fa = false) { - return $this->_config_data['ldap_in_group']; + $groups = trim($this->_config_data['ldap_in_group']); + if ((true === $included_without2fa) && ('' != $groups) && ('' != $this->GetLdapWithout2faInGroup())) { + $groups = $this->GetLdapWithout2faInGroup() . "," . $groups; + } + return $groups; + } + + + function SetLdapWithout2faInGroup( + $value + ) { + $this->_config_data['ldap_without2fa_in_group'] = trim($value); + + $ldap_without2fa_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + + $groups_array = array(); + $list = explode("\t", $this->GetGroupsList()); + $n = count($list); + for($i = 0; $i < $n; $i++) { + if($list[$i] != '') { + $this->SetGroup($list[$i]); + $groups_array[] = $this->GetGroupName(); + } + } + + foreach ($ldap_without2fa_in_group_array as $one_group) { + if (!in_array(trim($one_group), $groups_array)) { + if ('' != trim($one_group)) { + $this->CreateGroup('', trim($one_group), trim($one_group)); + } + } + } + } + + + function GetLdapWithout2faInGroup() + { + return $this->_config_data['ldap_without2fa_in_group']; } @@ -14040,8 +14078,8 @@ function GetLdapUsersList( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14137,7 +14175,7 @@ function GetLdapUsersList( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14230,7 +14268,7 @@ function GetLdapUsersList( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14402,8 +14440,8 @@ function GetLdapUsersInfoArray( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -14498,7 +14536,7 @@ function GetLdapUsersInfoArray( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if (2 == $this->GetLdapServerType()) { // Generic LDAP, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); @@ -14591,7 +14629,7 @@ function GetLdapUsersInfoArray( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -14892,8 +14930,8 @@ function SyncLdapUsers( // Prepare the array "users_in_groups" // - if we are using a generic LDAP and an LdapInGroup Filtering // - if we are using enhanced Active Directory - if ('' != trim($this->GetLdapInGroup())) { - $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup())))); + if ('' != trim($this->GetLdapInGroup(true))) { + $in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapInGroup(true))))); } else { $in_groups_array_raw = array(); } @@ -15044,7 +15082,7 @@ function SyncLdapUsers( $users_in_groups = array(); - if ('' != trim($this->GetLdapInGroup())) { + if ('' != trim($this->GetLdapInGroup(true))) { if ((2 == $this->GetLdapServerType()) || (4 == $this->GetLdapServerType())) { // Generic LDAP or eDirectory, eventually no memberOf function like in AD foreach ($in_groups_array_raw as $one_group) { @@ -15173,7 +15211,7 @@ function SyncLdapUsers( } if ($include_disabled || (!$accountdisable)) { // TODO $in_a_group discovery - if ('' == trim($this->GetLdapInGroup())) { + if ('' == trim($this->GetLdapInGroup(true))) { $in_a_group = TRUE; } else { $in_a_group = FALSE; @@ -15339,16 +15377,31 @@ function SyncLdapUsers( } $ldap_framedipnetmask = (isset($one_user['radiusframedipnetmask'][0]) ? ($one_user['radiusframedipnetmask'][0]) : "---"); + $ldap_algorithm = $this->GetLdapDefaultAlgorithm(); + if ('' != trim($this->GetLdapWithout2faInGroup())) { + $without2fa_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$this->GetLdapWithout2faInGroup())))); + $user_in_groups_array_raw = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$user_in_groups)))); + foreach ($without2fa_in_groups_array_raw as $one_without2fa_group) { + foreach ($user_in_groups_array_raw as $one_temp) { + if (strtolower($one_without2fa_group) == strtolower($one_temp)) { + $ldap_algorithm = "without2fa"; + break; + } + } + } + } + if (!$this->CheckUserExists($account, true, true)) { // $no_server_check = TRUE; $no_error = TRUE // User doesn't exist yet if ('' == $ldap_description) { $ldap_description = $account; } + $result = $this->FastCreateUser($account, $ldap_email, $ldap_sms, -1, // Prefix pin needed - $this->GetLdapDefaultAlgorithm(), + $ldap_algorithm, $ldap_enabled, $ldap_description, $ldap_group, @@ -15371,6 +15424,7 @@ function SyncLdapUsers( $existing_ldap_users_counter++; $this->SetUser($account); if (1 == $this->GetUserSynchronized()) { + $algorithm = $this->GetUserAlgorithm(); $description = $this->GetUserDescription(); $display_name = $this->GetUserDisplayName(); $email = $this->GetUserEmail(); @@ -15386,6 +15440,15 @@ function SyncLdapUsers( $modified = FALSE; $detailed_modif = ""; + // !!! Special without2fa behavior !!! + if ((('without2fa' == $ldap_algorithm) && ($algorithm != $ldap_algorithm)) || + (('without2fa' != $ldap_algorithm) && ('without2fa' == $algorithm) && ('' != trim($this->GetLdapWithout2faInGroup()))) + ) { + $this->SetUserAlgorithm($ldap_algorithm); + $modified = TRUE; + $detailed_modif = (('' != $detailed_modif) ? ', ' : '') . "Algorithm: $algorithm -> $ldap_algorithm"; + } + if (('' != $ldap_description) && ($description != $ldap_description)) { $this->SetUserDescription($ldap_description); $modified = TRUE; @@ -75163,6 +75226,10 @@ function clean_quotes( $multiotp->SetLdapUsersDn($actual_array[1]); $write_config_data = true; break; + case 'ldap-without2fa-in-group': + $multiotp->SetLdapWithout2faInGroup($actual_array[1]); + $write_config_data = true; + break; case 'log': $multiotp->SetLogOption(intval($actual_array[1])); $write_config_data = true; @@ -75865,6 +75932,7 @@ function clean_quotes( echo " ldap-time-limit: LDAP/AD number of sec. to wait for search results".$crlf; echo " ldap-users-dn: LDAP/AD users DN (optional, use base-dn if empty)".$crlf; echo " (you can put several DN separated by semicolons)".$crlf; + echo " ldap-without2fa-in-group: Special LDAP/AD group(s) for without2fa users".$crlf; echo " ldaptls_reqcert: ['auto'|'never'|''|...] how to perform the LDAP TLS".$crlf; echo " server certificate checks (LDAPTLS_REQCERT)".$crlf; echo " 'auto' means 'never' for Windows and '' for Linux".$crlf; diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/readme_5.9.4.0.txt b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/readme_5.9.5.0.txt similarity index 98% rename from raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/readme_5.9.4.0.txt rename to raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/readme_5.9.5.0.txt index 6301572..45edb57 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/readme_5.9.4.0.txt +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/readme_5.9.5.0.txt @@ -6,7 +6,7 @@ multiOTP open source is OATH certified for HOTP/TOTP (c) 2010-2022 SysCo systemes de communication sa https://www.multiotp.net/ -Current build: 5.9.4.0 (2022-11-04) +Current build: 5.9.5.0 (2022-11-11) Binary download: https://download.multiotp.net/ (including virtual appliance image) @@ -152,6 +152,7 @@ WHAT'S NEW IN THIS 5.9.x RELEASE CHANGE LOG OF RELEASED VERSIONS =============================== ``` +2022-11-11 5.9.5.0 ENH: It's now possible to define a special AD/LDAP group to attribute "Without2FA" token to specific users 2022-11-04 5.9.4.0 ENH: Enhanced multiOTP Credential Provider 2022-10-21 5.9.3.1 FIX: Better special characters support in username and password ENH: The locked accounts list now also list the temporary delayed accounts @@ -1556,7 +1557,7 @@ MULTIOTP COMMAND LINE TOOL ========================== ``` -multiOTP 5.9.4.0 (2022-11-04) +multiOTP 5.9.5.0 (2022-11-11) (c) 2010-2022 SysCo systemes de communication sa http://www.multiOTP.net (you can try the [Donate] button ;-) @@ -1771,6 +1772,7 @@ Usage: ldap-time-limit: LDAP/AD number of sec. to wait for search results ldap-users-dn: LDAP/AD users DN (optional, use base-dn if empty) (you can put several DN separated by semicolons) + ldap-without2fa-in-group: Special LDAP/AD group(s) for without2fa users ldaptls_reqcert: ['auto'|'never'|''|...] how to perform the LDAP TLS server certificate checks (LDAPTLS_REQCERT) 'auto' means 'never' for Windows and '' for Linux diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp-service.sh b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp-service.sh index 53cf36c..9715a6d 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp-service.sh +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp-service.sh @@ -16,8 +16,8 @@ # Please check https://www.multiotp.net/ and you will find the magic button ;-) # # @author Andre Liechti, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2013-11-29 # @copyright (c) 2013-2021 by SysCo systemes de communication sa # @copyright GNU Lesser General Public License diff --git a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp.pl b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp.pl index 70c78c8..42c8fe0 100644 --- a/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp.pl +++ b/raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/scripts/multiotp.pl @@ -15,8 +15,8 @@ # Please check https://www\.multiOTP.net/ and you will find the magic button ;-) # # @author SysCo/yj, SysCo/al, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2014-08-14 # @copyright (c) 2014-2022 SysCo systemes de communication sa # @copyright (c) 2002 by Boian Jordanov diff --git a/raspberry/boot-part/newvm.sh b/raspberry/boot-part/newvm.sh index cbcedf2..b2fa98e 100644 --- a/raspberry/boot-part/newvm.sh +++ b/raspberry/boot-part/newvm.sh @@ -8,8 +8,8 @@ # https://www.multiotp.net/ # # @author Andre Liechti, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2013-09-22 # @copyright (c) 2013-2022 SysCo systemes de communication sa # @copyright GNU Lesser General Public License @@ -38,7 +38,7 @@ # 2013-09-22 4.0.9.0 SysCo/al Initial release ########################################################################## -TEMPVERSION="@version 5.9.4.0" +TEMPVERSION="@version 5.9.5.0" MULTIOTPVERSION="$(echo -e "${TEMPVERSION:8}" | tr -d '[[:space:]]')" IFS='.' read -ra MULTIOTPVERSIONARRAY <<< "$MULTIOTPVERSION" MULTIOTPMAJORVERSION=${MULTIOTPVERSIONARRAY[0]} diff --git a/raspberry/how-to-build-a-raspberry-strong-authentication-server.txt b/raspberry/how-to-build-a-raspberry-strong-authentication-server.txt index 413597b..8f12ef4 100644 --- a/raspberry/how-to-build-a-raspberry-strong-authentication-server.txt +++ b/raspberry/how-to-build-a-raspberry-strong-authentication-server.txt @@ -4,7 +4,7 @@ How to build a Raspberry Pi RADIUS strong two factors authentication server in s (c) 2010-2022 SysCo systemes de communication sa https://www.multiotp.net/ -Current build: 5.9.4.0 (2022-11-04) +Current build: 5.9.5.0 (2022-11-11) Supported Raspberry Pi hardware: 1B/1B+/2B/3B/3B+/4B diff --git a/raspberry/multiotp-open-source-raspberry-img.txt b/raspberry/multiotp-open-source-raspberry-img.txt index 86c84df..c186543 100644 --- a/raspberry/multiotp-open-source-raspberry-img.txt +++ b/raspberry/multiotp-open-source-raspberry-img.txt @@ -5,7 +5,7 @@ multiOTP open source is a strong two-factor authentication device (c) 2010-2022 SysCo systemes de communication sa https://www.multiotp.net/ -Current build: 5.9.4.0 (2022-11-04) +Current build: 5.9.5.0 (2022-11-11) Check the readme file of the multiOTP open source edition for more information. diff --git a/scripts/multiotp-service.sh b/scripts/multiotp-service.sh index 53cf36c..9715a6d 100644 --- a/scripts/multiotp-service.sh +++ b/scripts/multiotp-service.sh @@ -16,8 +16,8 @@ # Please check https://www.multiotp.net/ and you will find the magic button ;-) # # @author Andre Liechti, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2013-11-29 # @copyright (c) 2013-2021 by SysCo systemes de communication sa # @copyright GNU Lesser General Public License diff --git a/scripts/multiotp.pl b/scripts/multiotp.pl index 70c78c8..42c8fe0 100644 --- a/scripts/multiotp.pl +++ b/scripts/multiotp.pl @@ -15,8 +15,8 @@ # Please check https://www\.multiOTP.net/ and you will find the magic button ;-) # # @author SysCo/yj, SysCo/al, SysCo systemes de communication sa, -# @version 5.9.4.0 -# @date 2022-11-04 +# @version 5.9.5.0 +# @date 2022-11-11 # @since 2014-08-14 # @copyright (c) 2014-2022 SysCo systemes de communication sa # @copyright (c) 2002 by Boian Jordanov diff --git a/webservice_install.cmd b/webservice_install.cmd index c4e4455..ab92f7b 100644 --- a/webservice_install.cmd +++ b/webservice_install.cmd @@ -9,8 +9,8 @@ REM REM Windows batch file for Windows 2K/XP/2003/7/2008/8/2012/10 REM REM @author Andre Liechti, SysCo systemes de communication sa, -REM @version 5.9.4.0 -REM @date 2022-11-04 +REM @version 5.9.5.0 +REM @date 2022-11-11 REM @since 2013-08-09 REM @copyright (c) 2013-2022 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License diff --git a/webservice_uninstall.cmd b/webservice_uninstall.cmd index 1d4dca7..6348aa7 100644 --- a/webservice_uninstall.cmd +++ b/webservice_uninstall.cmd @@ -9,8 +9,8 @@ REM REM Windows batch file for Windows 2K/XP/2003/7/2008/8/2012/10 REM REM @author Andre Liechti, SysCo systemes de communication sa, -REM @version 5.9.4.0 -REM @date 2022-11-04 +REM @version 5.9.5.0 +REM @date 2022-11-11 REM @since 2013-08-09 REM @copyright (c) 2013-2022 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License