Skip to content

Commit

Permalink
New release 5.9.5.0
Browse files Browse the repository at this point in the history
ENH: It's now possible to define a special AD/LDAP group to attribute "Without2FA" token to specific users
ENH: Default username and password are not displayed anymore if default password has been changed
  • Loading branch information
multiOTP committed Nov 11, 2022
1 parent 65b7f5f commit a6a7990
Show file tree
Hide file tree
Showing 29 changed files with 515 additions and 181 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Expand Up @@ -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, <info@multiotp.net>
# @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
Expand Down Expand Up @@ -46,7 +46,7 @@ MAINTAINER Andre Liechti <andre.liechti@multiotp.net>
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

Expand Down
14 changes: 8 additions & 6 deletions README.md
Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ;-)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
```
4 changes: 2 additions & 2 deletions check.multiotp.class.php
Expand Up @@ -22,8 +22,8 @@
* PHP 5.3.0 or higher is supported.
*
* @author Andre Liechti, SysCo systemes de communication sa, <info@multiotp.net>
* @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
Expand Down
4 changes: 2 additions & 2 deletions checkmultiotp.cmd
Expand Up @@ -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, <info@multiotp.net>
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
Expand Down
4 changes: 2 additions & 2 deletions launcher/ReadMe.txt
Expand Up @@ -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, <info@multiotp.net>
@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
Expand Down
8 changes: 4 additions & 4 deletions launcher/launcher.cpp
Expand Up @@ -14,8 +14,8 @@
* and run multiotp.windows.php with the provided arguments.
*
* @author Andre Liechti, SysCo systemes de communication sa, <info@multiotp.net>
* @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
Expand Down Expand Up @@ -68,8 +68,8 @@
#include <iostream>

#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())
Expand Down
111 changes: 87 additions & 24 deletions multiotp.class.php
Expand Up @@ -72,8 +72,8 @@
* PHP 5.3.0 or higher is supported.
*
* @author Andre Liechti, SysCo systemes de communication sa, <info@multiotp.net>
* @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
Expand Down Expand Up @@ -277,8 +277,8 @@ class Multiotp
* @brief Main class definition of the multiOTP project.
*
* @author Andre Liechti, SysCo systemes de communication sa, <info@multiotp.net>
* @version 5.9.4.0
* @date 2022-11-04
* @version 5.9.5.0
* @date 2022-11-11
* @since 2010-07-18
*/
{
Expand Down Expand Up @@ -376,8 +376,8 @@ class Multiotp
* @retval void
*
* @author Andre Liechti, SysCo systemes de communication sa, <info@multiotp.net>
* @version 5.9.4.0
* @date 2022-11-04
* @version 5.9.5.0
* @date 2022-11-11
* @since 2010-07-18
*/
function __construct(
Expand All @@ -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'); }
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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))));

Expand All @@ -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'];
}


Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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();
Expand All @@ -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;
Expand Down

0 comments on commit a6a7990

Please sign in to comment.