From c5dce87e81dceac22575768f710b70bc867d57d4 Mon Sep 17 00:00:00 2001 From: multiOTP Date: Thu, 19 Jan 2023 19:47:18 +0100 Subject: [PATCH] New release 5.9.5.5 ENH: LDAP filter can be customized using SetLdapFilter() method ({cn_identifier}, {username}, and {groups_filtering} placeholders are supported) ENH: Full PHP 8.x support (tested with 8.2.1 and 8.1.14), with backward compatibility support (7.x, >=5.4.x) ENH: Enhanced AD/LDAP paging support ENH: Embedded Windows nginx edition updated to version 1.22.1 ENH: Embedded Windows PHP edition updated to version 8.2.0 ENH: PHP 8.2.x deprecated code cleaned (nullable trim, dynamic properties, PostgreSQL command without connection argument) ENH: Enhanced sms library (MultiotpSms), new eCall API implementation, new ASPSMS API implementation ENH: Better MySQL error handling ENH: Better PostgreSQL error handling --- Dockerfile | 8 +- README.md | 79 +- check.multiotp.class.php | 10 +- checkmultiotp.cmd | 20 +- contrib/Base.php | 2 +- contrib/DES.php | 8 +- contrib/MultiotpAdLdap.php | 901 +++--- contrib/MultiotpSms.php | 46 +- contrib/MultiotpTools.php | 86 +- contrib/MultiotpXmlParser.php | 3 + contrib/Random.php | 4 + contrib/Rijndael.php | 3 + launcher/ReadMe.txt | 8 +- launcher/launcher.cpp | 12 +- multiotp.class.php | 1534 +++++----- multiotp.cli.header.php | 42 +- multiotp.cli.proxy.php | 10 +- multiotp.php | 2627 +++++++++-------- multiotp.server.php | 34 +- radius_debug.cmd | 8 +- radius_install.cmd | 8 +- radius_uninstall.cmd | 8 +- raspberry/boot-part/install.sh | 6 +- .../usr/local/bin/multiotp/index.php | 2615 ++++++++-------- .../usr/local/bin/multiotp/multiotp.class.php | 2581 +++++++++------- .../usr/local/bin/multiotp/multiotp.php | 10 +- .../usr/local/bin/multiotp/multiotp.proxy.php | 2627 +++++++++-------- ...{readme_5.9.5.1.txt => readme_5.9.5.5.txt} | 71 +- .../bin/multiotp/scripts/multiotp-service.sh | 4 +- .../local/bin/multiotp/scripts/multiotp.pl | 11 +- raspberry/boot-part/newvm.sh | 8 +- ...raspberry-strong-authentication-server.txt | 4 +- .../multiotp-open-source-raspberry-img.txt | 4 +- scripts/multiotp-service.sh | 4 +- scripts/multiotp.pl | 11 +- webservice_install.cmd | 9 +- webservice_uninstall.cmd | 8 +- 37 files changed, 7467 insertions(+), 5967 deletions(-) rename raspberry/boot-part/multiotp-tree/usr/local/bin/multiotp/{readme_5.9.5.1.txt => readme_5.9.5.5.txt} (96%) diff --git a/Dockerfile b/Dockerfile index 6d55a4b..991698c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,10 @@ # Please check https://www\.multiOTP.net/ and you will find the magic button ;-) # # @author Andre Liechti, SysCo systemes de communication sa, -# @version 5.9.5.1 -# @date 2022-11-11 +# @version 5.9.5.5 +# @date 2023-01-19 # @since 2013-11-29 -# @copyright (c) 2013-2022 SysCo systemes de communication sa +# @copyright (c) 2013-2023 SysCo systemes de communication sa # @copyright GNU Lesser General Public License # # docker build . @@ -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.5.1" + Version="5.9.5.5" ARG DEBIAN_FRONTEND=noninteractive diff --git a/README.md b/README.md index fc9e4a1..550ae3f 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ multiOTP open source multiOTP open source is a GNU LGPL implementation of a strong two-factor authentication PHP class multiOTP open source is OATH certified for HOTP/TOTP -(c) 2010-2022 SysCo systemes de communication sa +(c) 2010-2023 SysCo systemes de communication sa https://www.multiotp.net/ -Current build: 5.9.5.1 (2022-11-11) +Current build: 5.9.5.5 (2023-01-19) Binary download: https://download.multiotp.net/ (including virtual appliance image) @@ -22,7 +22,7 @@ PATH/TO/FREERADIUS/LOG/VOLUME:/var/log/freeradius The **multiotp/multiotp-open-source** docker is working on Synology devices ! -Binary download of the multiOTP open source Credential Provider V2 for Windows 7/8/8.1/10/2012(R2)/2016 with options like RDP only and UPN name support : https://download.multiotp.net/credential-provider/ +Binary download of the multiOTP open source Credential Provider for Windows 7/8/8.1/10/11/2012(R2)/2016/2019/2022 : https://download.multiotp.net/credential-provider/ [![Donate via PayPal](https://img.shields.io/badge/donate-paypal-87ceeb.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=USD&business=paypal@sysco.ch&item_name=Donation%20for%20multiOTP%20project) *Please consider supporting this project by making a donation via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=USD&business=paypal@sysco.ch&item_name=Donation%20for%20multiOTP%20project)* @@ -101,6 +101,7 @@ TABLE OF CONTENTS * How to install a local only strong authentication on a Windows machine ? * How to install a centralized strong authentication server for strong authentication on Windows desktops or RDP ? + * LDAP filter customization * OpenSSL options for LDAPS * Compatible clients applications and devices * External packages used @@ -144,6 +145,7 @@ subfolders from windows to your current multiOTP folder WHAT'S NEW IN THIS 5.9.x RELEASE +- LDAP filter can be customized - Users without 2FA tokens don't see the second screen in the Credential Provider during logon - New Raspberry, Hyper-V and OVA appliances available (version 011, based on Debian 11) - Scratchlist can be generated from the Web GUI @@ -151,9 +153,19 @@ WHAT'S NEW IN THIS 5.9.x RELEASE CHANGE LOG OF RELEASED VERSIONS =============================== -``` +2023-01-19 5.9.5.5 ENH: LDAP filter can be customized using SetLdapFilter() method + ({cn_identifier}, {username}, and {groups_filtering} placeholders are supported) + ENH: Full PHP 8.x support (tested with 8.2.1 and 8.1.14), + with backward compatibility support (7.x, >=5.4.x) + ENH: Enhanced AD/LDAP paging support +2022-12-31 5.9.5.3 ENH: Embedded Windows nginx edition updated to version 1.22.1 + ENH: Embedded Windows PHP edition updated to version 8.2.0 + ENH: PHP 8.2.x deprecated code cleaned (nullable trim, dynamic properties, PostgreSQL command without connection argument) + ENH: Enhanced sms library (MultiotpSms), new eCall API implementation, new ASPSMS API implementation + ENH: Better MySQL error handling + ENH: Better PostgreSQL error handling 2022-11-11 5.9.5.1 FIX: Windows nginx subfolders are now protected -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 + 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 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 @@ -757,18 +769,14 @@ in the radius server and provide the IP address(es) of the device(s) (often called NAS) and their shared Secret. If you want to have strong authentication on Windows logon, have a look at the -open source project multiOTPCredentialProvider which is based on MultiotpCPV2RDP from -arcadejust and MultiOneTimePassword Credential Provider from Last Squirrel IT. -It works with Windows 7/8/8.1/10/2012(R2)/2016 in both 32 and 64 bits. +open source project multiOTPCredentialProvider which is based on MultiotpCPV2RDP +from arcadejust and MultiOneTimePassword Credential Provider from Last Squirrel IT. +It works with Windows 7/8/8.1/10/11/2012(R2)/2016/2019/2022 in 64 bits. The Credential Provider does not need any RADIUS connection! It uses instead a local version of multiOTP which can be configured as a client of a centralized server (with caching support). (https://download.multiotp.net/credential-provider/) -LSE Experts provides a commercial Radius Credential Provider which can talk -directly with a radius server. -(http://www.lsexperts.de) - When the backend is set, it's time to create/define the tokens. You will have to select hardware or software token generators for your users. Currently, the library supports mOTP, TOTP, HOTP, SMS or scratch passwords (printed on paper). @@ -1296,10 +1304,16 @@ HOW TO CONFIGURE MULTIOTP TO SYNCHRONIZED THE USERS FROM A STANDARD LDAP ? 15) Set the transaction time limit multiotp -config ldap-time-limit=30 -16) Activate the AD/LDAP support (0|1): +16) (EXPERT ONLY) If needed, you can change the LDAP filter. + By default, the LDAP filter for standard LDAP is : + "(&(|(objectClass=posixAccount)(objectClass=user))({cn_identifier}={username}))" + You can use the following placeholders: {cn_identifier}, {username}, and {groups_filtering} + multiotp -config ldap-filter="(&(|(objectClass=posixAccount)(objectClass=user))({cn_identifier}={username}))" + +17) Activate the AD/LDAP support (0|1): multiotp -config ldap-activated=1 -17) Let's go for an AD/LDAP users synchronisation ! +18) Let's go for an AD/LDAP users synchronisation ! (users removed or deactivated in the AD/LDAP are deactivated in multiOTP) multiotp -debug -display-log -ldap-users-sync @@ -1351,7 +1365,7 @@ B) On the client(s) HOW TO INSTALL A LOCAL ONLY STRONG AUTHENTICATION ON A WINDOWS MACHINE ? ======================================================================== 1) Install multiOTPCredentialProvider, which contains also multiOTP inside. - It works with Windows 7/8/8.1/10/2012(R2)/2016 in both 32 and 64 bits. + It works with Windows 7/8/8.1/10/11/2012(R2)/2016/2019/2022 in 64 bits. (https://download.multiotp.net/credential-provider/) 2) During the installation, specify the folder on the client where the multiotp.exe file and folders must be installed and configured. @@ -1368,7 +1382,7 @@ FOR STRONG AUTHENTICATION ON WINDOWS DESKTOPS OR RDP ? ========================================================= 1) Install a client/server multiOTP environment like explained above. 2) On each client, install multiOTPCredentialProvider . - It works with Windows 7/8/8.1/10/2012(R2)/2016 in both 32 and 64 bits. + It works with Windows 7/8/8.1/10/11/2012(R2)/2016/2019/2022 in 64 bits. (https://download.multiotp.net/credential-provider/) 3) During the installation, specify the folder on the client where the multiotp.exe file and folders must be installed and configured. @@ -1450,6 +1464,11 @@ HOW TO BUILD A RASPBERRY PI STRONG AUTHENTICATION SERVER ? To adapt the freeradius configuration, edit the file /etc/freeradius/clients.conf. +LDAP FILTER CUSTOMIZATION +========================= +You can customize your own LDAP filter. By default, the LDAP filter is the following: + + OPENSSL OPTIONS FOR LDAPS ========================= You can define how the certificate bundle is handled with the ldaptls_reqcert option. @@ -1458,10 +1477,9 @@ You can define a custom cipher suite with the ldaptls_cipher_suite option. COMPATIBLE CLIENTS APPLICATIONS AND DEVICES =========================================== -Open source multiOTPCredentialProvider, based on MultiotpCPV2RDP and mOTP-CP. -If you want to have strong authentication on Windows logon, have a look at the -open source multiOTPCredentialProvider. -It works with Windows 7/8/8.1/10/2012(R2)/2016/2019 in both 32 and 64 bits. +Open source project multiOTPCredentialProvider which is based on MultiotpCPV2RDP +from arcadejust and MultiOneTimePassword Credential Provider from Last Squirrel IT. +It works with Windows 7/8/8.1/10/11/2012(R2)/2016/2019/2022 in 64 bits. The Credential Provider is using directly a local version of multiOTP which can be configured as a client of a centralized multiOTP server (with caching support) (https://github.com/multiOTP/multiOTPCredentialProvider) @@ -1493,8 +1511,8 @@ EXTERNAL PACKAGES AND SOFTWARE USED Joseph Myers, Paul Johnston, Greg Holt, Will Bond https://www.myersdaily.org/joseph/javascript/md5-text.html - multiOTPCredentialProvider, based on MultiotpCPV2RDP (Apache License) - Credential Provider (32 and 64 bits) supporting Windows 7/8/8.1/10/2012(R2)/2016 + multiOTP Credential Provider + Credential Provider (64 bits) supporting Windows 7/8/8.1/10/11/2012(R2)/2016/2019/2022 SysCo / ArcadeJust / LastSquirrelIT https://github.com/multiOTP/multiOTPCredentialProvider @@ -1559,8 +1577,8 @@ MULTIOTP COMMAND LINE TOOL ========================== ``` -multiOTP 5.9.5.1 (2022-11-11) -(c) 2010-2022 SysCo systemes de communication sa +multiOTP 5.9.5.5 (2023-01-19) +(c) 2010-2023 SysCo systemes de communication sa http://www.multiOTP.net (you can try the [Donate] button ;-) multiotp will check if the token of a user is correct, based on a specified @@ -1760,6 +1778,7 @@ Usage: ldap-default-algorithm: [totp|hotp|motp|without2fa] default algorithm for new LDAP/AD users ldap-domain-controllers: LDAP/AD domain controller(s), comma separated + ldap-filter: LDAP/AD filter customization (check documentation) ldap-group-attribute: LDAP/AD group attribute (default is memberOf) ldap-group-cn-identifier: LDAP/AD group cn identifier (default is sAMAccountName for AD, cn for LDAP) @@ -1775,10 +1794,10 @@ Usage: 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 + ldaptls-reqcert: ['auto'|'never'|''|...] how to perform the LDAP TLS server certificate checks (LDAPTLS_REQCERT) 'auto' means 'never' for Windows and '' for Linux - ldaptls_cipher_suite: ['auto'|''|...] which cipher suite is used for the + ldaptls-cipher-suite: ['auto'|''|...] which cipher suite is used for the LDAP TLS connection (LDAPTLS_CIPHER_SUITE) 'auto' means '' for PHP higher than 5.x and 'NORMAL:!VERS-TLS1.2' for PHP 5.x and before @@ -2074,8 +2093,8 @@ Visit https://forum.multiotp.net/ for additional support ``` ``` -Hash verification for multiotp_5.9.5.1.zip -SHA256:2c108f38727b3866c3974779047960364bd96c0ba66166a010e216cc2fd5a5ab -SHA1:852e0cc33700d50eb0c0250abbf11c6a4c417ce4 -MD5:fa787496fd37668a2730e19bae057d09 +Hash verification for multiotp_5.9.5.5.zip +SHA256:2c74456fabb492fd290d4cd78330da99ef30e3991ec75d5f7c5235f006774f1c +SHA1:93e198f68850c57a7c14e5a4a72f654722c929e4 +MD5:992e16fedf5bd654e737918aeb9de6bc ``` diff --git a/check.multiotp.class.php b/check.multiotp.class.php index 26957a5..2e66bd9 100644 --- a/check.multiotp.class.php +++ b/check.multiotp.class.php @@ -19,20 +19,20 @@ * WARNING! DO NOT FORGET TO REMOVE this test file from your disk when you go in production ! * * - * PHP 5.3.0 or higher is supported. + * PHP 5.4.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.5.1 - * @date 2022-11-11 + * @version 5.9.5.5 + * @date 2023-01-19 * @since 2013-07-10 - * @copyright (c) 2013-2022 SysCo systemes de communication sa + * @copyright (c) 2013-2023 SysCo systemes de communication sa * @copyright GNU Lesser General Public License * *//* * * LICENCE * - * Copyright (c) 2013-2022 SysCo systemes de communication sa + * Copyright (c) 2013-2023 SysCo systemes de communication sa * SysCo (tm) is a trademark of SysCo systemes de communication sa * (http://www.sysco.ch/) * All rights reserved. diff --git a/checkmultiotp.cmd b/checkmultiotp.cmd index 2dffa0d..5c08b44 100644 --- a/checkmultiotp.cmd +++ b/checkmultiotp.cmd @@ -11,10 +11,10 @@ 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.5.1 -REM @date 2022-11-11 +REM @version 5.9.5.5 +REM @date 2023-01-19 REM @since 2010-07-10 -REM @copyright (c) 2010-2022 SysCo systemes de communication sa +REM @copyright (c) 2010-2023 SysCo systemes de communication sa REM @copyright GNU Lesser General Public License REM REM @@ -38,7 +38,7 @@ REM REM REM Licence REM -REM Copyright (c) 2010-2022 SysCo systemes de communication sa +REM Copyright (c) 2010-2023 SysCo systemes de communication sa REM SysCo (tm) is a trademark of SysCo systemes de communication sa REM (http://www.sysco.ch/) REM All rights reserved. @@ -114,7 +114,7 @@ IF NOT %ERRORLEVEL% == 0 ( :NoWarning REM UTF-8 mode -CHCP 65001 +CHCP 65001 >NUL IF EXIST "%TEMP%\multiotp_error.log" DEL "%TEMP%\multiotp_error.log" /Q @@ -202,6 +202,8 @@ REM Set the backend ECHO. ECHO Backend is set to %_backend% %_multiotp% -config backend-type=%_backend% + +ECHO Initialize backend IF "mysql"=="%_backend%" %_multiotp% -display-log -initialize-backend IF "pgsql"=="%_backend%" %_multiotp% -display-log -initialize-backend @@ -596,11 +598,11 @@ ECHO Check test_user2 to see if it is not a without 2FA token IF ERRORLEVEL 8 ECHO - KO! Error 8 checking the user test_user2 token type IF ERRORLEVEL 8 ECHO - KO! Error 8 checking the user test_user2 token type (%_backend%) >>"%TEMP%\multiotp_error.log" IF ERRORLEVEL 8 GOTO CheckIsNotWithout2FA +IF NOT ERRORLEVEL 7 ECHO - KO! Error checking the user test_user2 token type +IF NOT ERRORLEVEL 7 ECHO - KO! Error checking the user test_user2 token type (%_backend%) >>"%TEMP%\multiotp_error.log" +IF NOT ERRORLEVEL 7 GOTO CheckIsNotWithout2FA IF ERRORLEVEL 7 ECHO - OK! Token of the user test_user2 is a without 2FA token IF ERRORLEVEL 7 SET /A SUCCESSES=SUCCESSES+1 -IF ERRORLEVEL 7 GOTO CheckIsNotWithout2FA -ECHO - KO! Error checking the user test_user2 token type -ECHO - KO! Error checking the user test_user2 token type (%_backend%) >>"%TEMP%\multiotp_error.log" :CheckIsNotWithout2FA SET /A TOTAL_TESTS=TOTAL_TESTS+1 @@ -689,7 +691,7 @@ REM List of attributes to encrypt is set to default value ECHO. ECHO End of the CLI multiOTP tests -IF %SUCCESSES% EQU %TOTAL_TESTS% ECHO (everything is OK so far...) +IF %SUCCESSES% EQU %TOTAL_TESTS% ECHO (all %TOTAL_TESTS% tests are OK so far...) ECHO. diff --git a/contrib/Base.php b/contrib/Base.php index 41560a7..6bf3b64 100644 --- a/contrib/Base.php +++ b/contrib/Base.php @@ -1941,7 +1941,7 @@ function _clearBuffers() // mcrypt's handling of invalid's $iv: // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size); - $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0"); + $this->encryptIV = $this->decryptIV = str_pad(substr((is_null($this->iv) ? "" : $this->iv), 0, $this->block_size), $this->block_size, "\0"); if (!$this->skip_key_adjustment) { $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0"); diff --git a/contrib/DES.php b/contrib/DES.php index 3cec249..df9f44d 100644 --- a/contrib/DES.php +++ b/contrib/DES.php @@ -130,6 +130,9 @@ */ class Crypt_DES extends Crypt_Base { + // PHP >= 8.1 + var $kl = array(); + /** * Block Length of the cipher * @@ -1319,9 +1322,10 @@ function _setupKey() $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF]; // Reorder: odd bytes/even bytes. Push the result in key schedule. - $val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) | + // PHP >= 8.1 + $val1 = ( $cp & intval(0xFF000000)) | (($cp << 8) & 0x00FF0000) | (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); - $val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) | + $val2 = (($cp << 8) & intval(0xFF000000)) | (($cp << 16) & 0x00FF0000) | (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val1; $keys[$des_round][CRYPT_DES_DECRYPT][$ki - 1] = $val1; diff --git a/contrib/MultiotpAdLdap.php b/contrib/MultiotpAdLdap.php index 9215545..95191f8 100644 --- a/contrib/MultiotpAdLdap.php +++ b/contrib/MultiotpAdLdap.php @@ -3,14 +3,18 @@ PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY Version 2.1+ - Adapted 2013-2021 by SysCo/al 5.8.2.1 (2021-04-07) + Adapted 2013-2022 by SysCo/al 5.9.5.5 (2023-01-18) * * + * 2023-01-18 5.9.5.5 SysCo/al New _ldap_filter attribute + * New paging support for 7.3+ + * * 2021-04-07 5.8.2.1 SysCo/al Test connection filter changed from (dn=test-connection) to (objectClass=user) * (dn=xxx not supported by eDirectory) * New LDAP type 4 for eDirectory : users are searched with the class posixAccount or user * enhanced LDAP type 2 : users are searched with the class posixAccount or user + * * 2018-07-16 5.2.0.0 SysCo/al Active Directory support enhancement (member:1.2.840.113556.1.4.1941:=) * Active Directory primary group optimized detection * _users_dn added @@ -70,7 +74,7 @@ Attributes documentation : http://www.selfadsi.org/user-attributes.htm LDAP information, also for other implementation: https://github.com/mfreiholz/iF.SVNAdmin/issues/53 - LDAP trick for > 1000: http://php.net/manual/fr/function.ldap-search.php + LDAP trick for > 1000: http://php.net/manual/en/function.ldap-search.php */ // Added by SysCo/al @@ -185,7 +189,12 @@ class MultiotpAdLdap { var $_error_message; // Added by SysCo/al var $_error_no; // Added by SysCo/al var $_ldap_server_type; // Added by SysCo/al, 1 (default) for Active Directory, 2 for Generic LDAP, 3 for legacy Active Directory, 4 for eDirectory (Novell) + var $_ldap_filter; // Added by SysCo/al var $_oui_sr; // Added by SysCo/al + var $_paging_cookie; // Added 2023 by SysCo/al + var $_paging_legacy; // Added 2023 by SysCo/al + var $_paging_ldap_control; // Added 2023 by SysCo/al + var $_paging_size; // Added 2023 by SysCo/al var $_debug_message; // Added by SysCo/al 4.3.2.2 var $_warning_message; // Added by SysCo/al var $_server_reachable; // Added by SysCo/al @@ -195,6 +204,10 @@ class MultiotpAdLdap { var $_cache_timeout = 3600; // Added by SysCo/al var $_linux_file_mode = '0666'; // Added by SysCo/al + + // Creation of dynamic property is deprecated + var $_oui_paged_sr; + var $_expired_password_valid; // default constructor function __construct($options=array()) { @@ -209,7 +222,13 @@ function __construct($options=array()) { $this->_error_message = ''; // Added by SysCo/al $this->_error_no = 0; // Added by SysCo/al $this->_ldap_server_type = 1; // Added by SysCo/al + $this->_ldap_filter = ''; // Added by SysCo/al $this->_oui_paged_sr = NULL; // Added by SysCo/al + $this->_paging_cookie = ''; + $this->_paging_legacy = false; + $this->_paging_ldap_control = false; + $this->_paging_size = 1000; + $this->_debug_message = ''; // Added by SysCo/al $this->_warning_message = ''; // Added by SysCo/al $this->_server_reachable = FALSE; // Added by SysCo/al @@ -227,6 +246,7 @@ function __construct($options=array()) { if (array_key_exists("use_ssl",$options)){ $this->_use_ssl=$options["use_ssl"]; } if (array_key_exists("recursive_groups",$options)){ $this->_recursive_groups=$options["recursive_groups"]; } if (array_key_exists("ldap_server_type",$options)){ $this->_ldap_server_type=$options["ldap_server_type"]; } + if (array_key_exists("ldap_filter ",$options)){ $this->_ldap_filter=$options["ldap_filter"]; } if (array_key_exists("cache_support",$options)){ $this->_cache_support=$options["cache_support"]; } if (array_key_exists("cache_folder",$options)){ $this->_cache_folder=$options["cache_folder"]; } if (array_key_exists("expired_password_valid",$options)){ $this->_expired_password_valid=(TRUE == $options["expired_password_valid"]); } @@ -286,7 +306,7 @@ function __construct($options=array()) { ldap_set_option($this->_conn, LDAP_OPT_NETWORK_TIMEOUT, intval($options["network_timeout"])); ldap_set_option($this->_conn_paged, LDAP_OPT_NETWORK_TIMEOUT, intval($options["network_timeout"])); } - + ldap_set_option($this->_conn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($this->_conn_paged, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($this->_conn, LDAP_OPT_REFERRALS, 0); @@ -296,10 +316,30 @@ function __construct($options=array()) { ldap_set_option($this->_conn, LDAP_OPT_RESTART, 1); ldap_set_option($this->_conn_paged, LDAP_OPT_RESTART, 1); + // Added 2023-01-01 + $this->_paging_ldap_control = false; // Will be detected further + if (PHP_VERSION_ID >= 70300) { + $this->_paging_legacy = false; + } else { + $this->_paging_legacy = true; + } + //bind as a domain admin if they've set it up $this->_bind = @ldap_bind($this->_conn,$this->_ad_username.$this->_account_suffix,$this->_ad_password); $this->_bind_paged = @ldap_bind($this->_conn_paged,$this->_ad_username.$this->_account_suffix,$this->_ad_password); if ($this->_bind) { + + + if (PHP_VERSION_ID >= 70300) { + $ldap_result = ldap_read($this->_conn, '', '(objectClass=*)', ['supportedControl']); + if (in_array(LDAP_CONTROL_PAGEDRESULTS, ldap_get_entries($this->_conn, $ldap_result)[0]['supportedcontrol'])) { + $this->_paging_ldap_control = true; + } else { + $this->_paging_ldap_control = false; + } + } + + // Check BaseDN access, no paging needed if (FALSE !== (@ldap_search($this->_conn, $this->_base_dn, "(objectClass=user)"))) { $this->_error = FALSE; $this->_error_message = ''; @@ -370,6 +410,13 @@ function __construct($options=array()) { return ($connected); // But it's the constructor, the result cannot be used } + function set_paging_size($paging_size) { + $this->_paging_size = $paging_size; + } + + function get_paging_size() { + return ($this->_paging_size); + } function set_base_dn($base_dn) { $this->_base_dn = $base_dn; @@ -441,9 +488,6 @@ function ldap_get_one_entry_raw($id = "GENERIC", $first = FALSE, $srch_id = FALS $attributes = ldap_get_attributes($linkIdentifier, $this->_entry_identifier[$id]); $distinguishedname_in_attributes = FALSE; -// echo "DEBUG attributes\n"; -// print_r($attributes); - for($j=0; $j<$attributes['count']; $j++) { if ('distinguishedname' == strtolower($attributes[$j])) { @@ -473,14 +517,11 @@ function ldap_get_entries_raw($srch_id, $id = "ALL-IN-ONE-LOOP") $rawData = array(); $rawData['count'] = 0; // To be compatible with the old data organisation (counter at the beginning) $i = 0; - if ($result = $this->ldap_get_one_entry_raw($id, TRUE, $srch_id)) - { - do - { + if ($result = $this->ldap_get_one_entry_raw($id, TRUE, $srch_id)) { + do { $rawData[$i] = $result; $i++; - } - while ($result = $this->ldap_get_one_entry_raw($id)); + } while ($result = $this->ldap_get_one_entry_raw($id)); } unset($this->_entry_identifier[$id]); $rawData['count'] = $i; // and not count($rawData) because of the ['count'] argument @@ -657,29 +698,35 @@ function group_del_user($group,$user){ } // Returns an array of information for a specified group - function group_info($group_name,$fields=NULL){ - if ($group_name==NULL){ return (false); } - if (!$this->_bind){ return (false); } - + function group_info( + $group_name, + $fields=NULL + ) { + if ($group_name==NULL) { + return (false); + } + if (!$this->_bind) { + return (false); + } + $filter="(&(objectCategory=group)(".$this->_group_cn_identifier."=".$this->ldap_search_encode($group_name)."))"; - if ($fields==NULL){ $fields=array("member",$this->_group_attribute,"cn","description","distinguishedname","objectcategory",$this->_group_cn_identifier); } - - $sr=@ldap_search($this->_conn,$this->_base_dn,$filter,$fields); + if ($fields==NULL) { + $fields=array("member",$this->_group_attribute,"cn","description","distinguishedname","objectcategory",$this->_group_cn_identifier); + } + + // Search info for a specific group, no paging needed + $sr = @ldap_search($this->_conn, $this->_base_dn, $filter, $fields); if (FALSE === $sr) { $this->_warning_message = "group_info: ldap_search error ".ldap_errno($this->_conn).": ".ldap_error($this->_conn); - echo "DEBUG: ".$this->_warning_message."\n"; + // echo "DEBUG: ".$this->_warning_message."\n"; } - // Search: (&(objectCategory=group)(cn=gr10000)) - // (&(objectCategory=group)(cn=gr10)) - // PHP Warning: ldap_search(): Search: Critical extension is unavailable in // C:\data\projects\multiotp\core\contrib\MultiotpAdLdap.php on line 591 - // Search: (&(objectCategory=group)(cn=gr10)) $entries = $this->ldap_get_entries_raw($sr); // DEBUG if (0 == count($entries)) { $this->_warning_message = "group_info: No entry for the specified filter $filter"; - echo "DEBUG: ".$this->_warning_message."\n"; + // echo "DEBUG: ".$this->_warning_message."\n"; } return ($entries); @@ -695,10 +742,8 @@ function recursive_groups($group, $cache_only = FALSE) { $ret_groups=array(); $ret_data = FALSE; -/* - echo "DEBUG GROUP is group $group in cache ?\n"; - print_r($this->_cache_recursive_groups); -*/ + // echo "DEBUG GROUP is group $group in cache ?\n"; + // print_r($this->_cache_recursive_groups); clearstatcache(); @@ -773,17 +818,19 @@ function user_create($attributes){ if (!array_key_exists("container",$attributes)){ return ("Missing compulsory field [container]"); } if (!is_array($attributes["container"])){ return ("Container attribute must be an array."); } - if (array_key_exists("password",$attributes) && !$this->_use_ssl){ - // Modified by SysCo/al - $this->_error = TRUE; - $this->_error_message = 'FATAL: SSL must be configured on your webserver and enabled in the class to set passwords.'; - exit(); + if (array_key_exists("password",$attributes) && !$this->_use_ssl) { + // Modified by SysCo/al + $this->_error = TRUE; + $this->_error_message = 'FATAL: SSL must be configured on your webserver and enabled in the class to set passwords.'; + exit(); } - if (!array_key_exists("display_name",$attributes)){ $attributes["display_name"]=$attributes["firstname"]." ".$attributes["surname"]; } + if (!array_key_exists("display_name",$attributes)) { + $attributes["display_name"]=$attributes["firstname"]." ".$attributes["surname"]; + } //translate the schema - $add=$this->adldap_schema($attributes); + $add = $this->adldap_schema($attributes); //additional stuff only used for adding accounts $add["cn"][0]=$attributes["display_name"]; @@ -814,66 +861,89 @@ function user_create($attributes){ // group_users($group_name) // Returns an array of users that are members of a group - function group_users($group_name=NUL){ - $result = array(); - if ($group_name==NULL){ return (false); } - if (!$this->_bind){ return (false); } - $filter="(&(|(objectClass=posixGroup)(objectClass=groupofNames))(".$this->_group_cn_identifier."=".$this->ldap_search_encode($group_name)."))"; - $fields=array("member","memberuid"); - $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); - if (FALSE === $sr) { - $this->_warning_message = "group_users: ldap_search error ".ldap_errno($this->_conn).": ".ldap_error($this->_conn); - echo "DEBUG: ".$this->_warning_message."\n"; - } - $entries = $this->ldap_get_entries_raw($sr); + function group_users( + $group_name=NUL + ) { + $result = array(); + if ($group_name==NULL) { + return (false); + } + if (!$this->_bind) { + return (false); + } - // DEBUG - if (0 == count($entries)) { - $this->_warning_message = "group_users: No entry for the specified filter $filter"; - echo "DEBUG: ".$this->_warning_message; + if ((2 == $this->_ldap_server_type) || (4 == $this->_ldap_server_type)) { // Generic LDAP or eDirectory + $filter = "(&(|(objectClass=posixGroup)(objectClass=groupofNames))(".$this->_group_cn_identifier."=".$this->ldap_search_encode($group_name)."))"; + } else { // Active Directory + $group_account_type = "(|(samaccounttype=".ADLDAP_SECURITY_LOCAL_GROUP.")(samaccounttype=". ADLDAP_SECURITY_GLOBAL_GROUP."))"; + $filter = "(&(objectCategory=group)".$group_account_type."(".$this->_group_cn_identifier."=".$this->ldap_search_encode($group_name)."))"; + } + + $fields = array("member", "memberuid"); + $paging_cookie = ''; + + // New paging support for PHP 7.3+, paging loop not implemented yet + if ($this->_paging_ldap_control) { + $sr = ldap_search($this->_conn, $this->_base_dn, $filter, $fields, + 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => $this->_paging_size, 'cookie' => $paging_cookie]]]); + ldap_parse_result($this->_conn, $sr, $error_code , $matched_dn , $error_message , $referrals, $controls); + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + $paging_cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $paging_cookie = ''; } + } else { + $sr = ldap_search($this->_conn, $this->_base_dn, $filter, $fields); + } - if (isset($entries[0]["member"][0])) - { - $result = $this->nice_names($entries[0]["member"]); - /* - for ($i=0; $i++; $i < $entries[0]["member"][count]) - { - $result[] == ($entries[0]["member"][$i]); - } - */ - } - elseif (isset($entries[0]["memberuid"][0])) - { - $result = $this->nice_names($entries[0]["memberuid"]); - } - else + if (FALSE === $sr) { + $this->_warning_message = "group_users: ldap_search error ".ldap_errno($this->_conn).": ".ldap_error($this->_conn); + // echo "DEBUG: ".$this->_warning_message."\n"; + } + $entries = $this->ldap_get_entries_raw($sr); + + if (0 == count($entries)) { + $this->_warning_message = "group_users: No entry for the specified filter $filter"; + // echo "DEBUG: ".$this->_warning_message; + } + + if (isset($entries[0]["member"][0])) { + $result = $this->nice_names($entries[0]["member"]); + /* + for ($i=0; $i++; $i < $entries[0]["member"][count]) { - $result = array(); + $result[] == ($entries[0]["member"][$i]); } - return ($result); + */ + } + elseif (isset($entries[0]["memberuid"][0])) { + $result = $this->nice_names($entries[0]["memberuid"]); + } else { + $result = array(); + } + return ($result); } - // user_groups($user) // Returns an array of groups that a user is a member off function user_groups($username,$recursive=NULL){ - if ($username==NULL){ return (false); } - if ($recursive==NULL){ $recursive=$this->_recursive_groups; } //use the default option if they haven't set it - if (!$this->_bind){ return (false); } - - //search the directory for their information - $info=@$this->user_info($username,array($this->_group_attribute,"member","primarygroupid")); - - $groups=$this->nice_names($info[0][$this->_group_attribute]); //presuming the entry returned is our guy (unique usernames) - - if ($recursive){ - foreach ($groups as $id => $group_name){ - $extra_groups=$this->recursive_groups($group_name); - $groups=array_merge($groups,$extra_groups); - } - } - return ($groups); + if ($username==NULL){ return (false); } + if ($recursive==NULL){ $recursive=$this->_recursive_groups; } //use the default option if they haven't set it + if (!$this->_bind){ return (false); } + + //search the directory for their information + $info=@$this->user_info($username,array($this->_group_attribute,"member","primarygroupid")); + + $groups=$this->nice_names($info[0][$this->_group_attribute]); //presuming the entry returned is our guy (unique usernames) + + if ($recursive){ + foreach ($groups as $id => $group_name){ + $extra_groups=$this->recursive_groups($group_name); + $groups=array_merge($groups,$extra_groups); + } + } + return ($groups); } @@ -890,29 +960,31 @@ function rCountRemover($arr) { // New function, for enhanced Active Directory function user_all_groups($username, $groups_filtering = '') { - if ($username==NULL){ return (false); } - if (!$this->_bind){ return (false); } - $filter = "(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=".$username.")".$groups_filtering.")"; - // $fields = array($this->_group_cn_identifier,$this->_group_attribute,"distinguishedname"); - $fields = array("cn"); - $sr = ldap_search($this->_conn,$this->_base_dn,$filter, $fields); - if (FALSE === $sr) { - $this->_warning_message = "user_all_groups: ldap_search error ".ldap_errno($this->_conn).": ".ldap_error($this->_conn); - echo "DEBUG: ".$this->_warning_message."\n"; - } - $group_entries = $this->rCountRemover(ldap_get_entries($this->_conn, $sr)); + if ($username==NULL){ return (false); } + if (!$this->_bind){ return (false); } + $filter = "(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=".$username.")".$groups_filtering.")"; + // $fields = array($this->_group_cn_identifier,$this->_group_attribute,"distinguishedname"); + $fields = array("cn"); + // Search all groups of one user, it should not reach the paging size, no paging implemented + $sr = ldap_search($this->_conn, $this->_base_dn, $filter, $fields); + if (FALSE === $sr) { + $this->_warning_message = "user_all_groups: ldap_search error ".ldap_errno($this->_conn).": ".ldap_error($this->_conn); + // echo "DEBUG: ".$this->_warning_message."\n"; + } + $group_entries = $this->rCountRemover(ldap_get_entries($this->_conn, $sr)); + + // echo "DEBUG: info group_entries\n"; + // print_r($group_entries); + + $group_array = array(); + foreach ($group_entries as $group_entry) { + $group_array[] = $group_entry['cn'][0]; + } -//echo "DEBUG: info group_entries\n"; -//print_r($group_entries); - - $group_array = array(); - foreach ($group_entries as $group_entry) { - $group_array[] = $group_entry['cn'][0]; - } -//echo "DEBUG: group_array\n"; -//print_r($group_array); + // echo "DEBUG: group_array\n"; + // print_r($group_array); - return ($group_array); + return ($group_array); } @@ -931,129 +1003,161 @@ function users_info($username=NULL, $fields=NULL, $groups_filtering = '') } while ($result = $this->one_user_info()); } $entries['count'] = $i; // and not count($entries) because of the ['count'] argument - return ($entries); + return ($entries); } - // Added 2014-07-21 by SysCo/al, enhanced 2018-07-12 - function one_user_info($first = FALSE, $username = NULL, $fields = NULL, $group_cn_cache_only = FALSE, $groups_filtering = '', $in_groups_filtering = array()) - { - $this->_warning_message = ''; - $sr = FALSE; - if ($first) { - if ($username==NULL){ return (false); } - if (!$this->_bind_paged){ return (false); } - if ('' == $this->_users_dn) { - $this->_users_dn = $this->_base_dn; - } + // Added 2014-07-21 by SysCo/al, enhanced 2018-07-12 and 2023-01-02 + function one_user_info( + $first = FALSE, + $username = NULL, + $fields = NULL, + $group_cn_cache_only = FALSE, + $groups_filtering = '', + $in_groups_filtering = array() + ) { + $this->_warning_message = ''; + $sr = FALSE; + if ($first) { + if ($username==NULL){ + return (false); + } + if (!$this->_bind_paged){ + return (false); + } + if ('' == $this->_users_dn) { + $this->_users_dn = $this->_base_dn; + } - if (1 == $this->_ldap_server_type) { // Active Directory - $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$username.")".$groups_filtering.")"; - if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","telephonenumber","primarygroupid","distinguishedname"); } - } elseif (3 == $this->_ldap_server_type) { // legacy Active Directory - $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$username."))"; - if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","telephonenumber","primarygroupid","distinguishedname"); } - } else { // eDirectory (4) or Generic LDAP (2) or others - $filter = "(&(|(objectClass=posixAccount)(objectClass=user))(".$this->_cn_identifier."=".$username."))"; - if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","gecos","description","displayname","telephonenumber","gidnumber","distinguishedname"); } - } - $this->_oui_paged_sr = @ldap_search($this->_conn_paged,$this->_users_dn,$filter,$fields); - if (4 == ldap_errno($this->_conn_paged)) { - $cr = @ldap_count_entries($this->_conn_paged,$this->_oui_paged_sr); - $this->_warning_message = "LDAP server cannot return more than $cr records."; - } - // echo "DEBUG: Error: ".ldap_errno($this->_conn_paged); - // $cr = ldap_count_entries($this->_conn_paged,$sr); - // echo $cr; - // echo "DEBUG: Error: ".ldap_errno($this->_conn_paged); - } - if ($one_entry = $this->ldap_get_one_entry_raw("ONE_USER", $first, $this->_oui_paged_sr, $this->_conn_paged)) { - // AD does not return the primary group in the ldap query, we may need to fudge it - // SysCo/al added a test to check if $entries[0]["primarygroupid"][0] exists - $add_primary_group = FALSE; - if ($this->_real_primarygroup) { - if (isset($one_entry["primarygroupid"][0])) { - $pri_grp_rid = $one_entry["primarygroupid"][0]; - if (isset($this->_cache_group_dn[$pri_grp_rid])) { - $dn_group = $this->_cache_group_dn[$pri_grp_rid]; - $one_entry[$this->_group_attribute][] = $dn_group; - $add_primary_group = TRUE; - } else { - $r = ldap_read($this->_conn, $this->_base_dn, "(objectclass=*)", array("objectSid")) or exit(); - $data = ldap_get_entries($this->_conn, $r); - if (isset($data[0]["objectsid"][0])) { - $domain_sid = $data[0]["objectsid"][0]; - $domain_sid_s = sid2str($domain_sid); - $r = ldap_search($this->_conn, $this->_base_dn, "objectSid=".$domain_sid_s."-".$pri_grp_rid, array("distinguishedname")) or exit(); - $data = ldap_get_entries($this->_conn, $r); - if (isset($data[0]["distinguishedname"][0])) { - $dn_group = $data[0]["distinguishedname"][0]; - $one_entry[$this->_group_attribute][] = $dn_group; - $add_primary_group = TRUE; - if (count($this->_cache_group_dn) < 1000) { // Don't overload the memory cache - $this->_cache_group_dn[$pri_grp_rid] = $dn_group; - } - } - } - } - } + if (1 == $this->_ldap_server_type) { // Active Directory + $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$username.")".$groups_filtering.")"; + if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","telephonenumber","primarygroupid","distinguishedname"); } + } elseif (3 == $this->_ldap_server_type) { // legacy Active Directory + $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$username."))"; + if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","telephonenumber","primarygroupid","distinguishedname"); } + } else { // eDirectory (4) or Generic LDAP (2) or others + $filter = "(&(|(objectClass=posixAccount)(objectClass=user))(".$this->_cn_identifier."=".$username."))"; + if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","gecos","description","displayname","telephonenumber","gidnumber","distinguishedname"); } + } + if ("" != $this->_ldap_filter) { + $filter = $this->_ldap_filter; + $filter = str_replace('{cn_identifier}', $this->_cn_identifier, $filter); + $filter = str_replace('{username}', $username, $filter); + $filter = str_replace('{groups_filtering}', $groups_filtering, $filter); + } + + // New paging support for PHP 7.3+, old and new paging implemented outside the function + if ($this->_paging_ldap_control) { + $this->_oui_paged_sr = @ldap_search($this->_conn_paged, $this->_users_dn, $filter, $fields, + 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => $this->_paging_size, 'cookie' => $this->_paging_cookie]]]); + ldap_parse_result($this->_conn_paged, $this->_oui_paged_sr, $error_code , $matched_dn , $error_message , $referrals, $controls); + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + $this->_paging_cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $this->_paging_cookie = ''; + } + } else { + $this->_oui_paged_sr = @ldap_search($this->_conn_paged, $this->_users_dn, $filter, $fields); + } + + if (4 == ldap_errno($this->_conn_paged)) { // 4 = LDAP_SIZELIMIT_EXCEEDED + $cr = @ldap_count_entries($this->_conn_paged, $this->_oui_paged_sr); + $this->_warning_message = "LDAP server cannot return more than $cr records."; + } + // echo "DEBUG: Error: ".ldap_errno($this->_conn_paged); + // $cr = ldap_count_entries($this->_conn_paged,$sr); + // echo $cr; + // echo "DEBUG: Error: ".ldap_errno($this->_conn_paged); + } + if ($one_entry = $this->ldap_get_one_entry_raw("ONE_USER", $first, $this->_oui_paged_sr, $this->_conn_paged)) { + // AD does not return the primary group in the ldap query, we may need to fudge it + // SysCo/al added a test to check if $entries[0]["primarygroupid"][0] exists + $add_primary_group = FALSE; + if ($this->_real_primarygroup) { + if (isset($one_entry["primarygroupid"][0])) { + $pri_grp_rid = $one_entry["primarygroupid"][0]; + if (isset($this->_cache_group_dn[$pri_grp_rid])) { + $dn_group = $this->_cache_group_dn[$pri_grp_rid]; + $one_entry[$this->_group_attribute][] = $dn_group; + $add_primary_group = TRUE; } else { - $one_entry[$this->_group_attribute][]="CN=Domain Users,CN=Users,".$this->_base_dn; - $add_primary_group = TRUE; + $r = ldap_read($this->_conn, $this->_base_dn, "(objectclass=*)", array("objectSid")) or exit(); + $data = ldap_get_entries($this->_conn, $r); + if (isset($data[0]["objectsid"][0])) { + $domain_sid = $data[0]["objectsid"][0]; + $domain_sid_s = sid2str($domain_sid); + // No paging implemented here, it's a specific object, no paging needed + $r = ldap_search($this->_conn, $this->_base_dn, "objectSid=".$domain_sid_s."-".$pri_grp_rid, array("distinguishedname")) or exit(); + $data = ldap_get_entries($this->_conn, $r); + if (isset($data[0]["distinguishedname"][0])) { + $dn_group = $data[0]["distinguishedname"][0]; + $one_entry[$this->_group_attribute][] = $dn_group; + $add_primary_group = TRUE; + if (count($this->_cache_group_dn) < 1000) { // Don't overload the memory cache + $this->_cache_group_dn[$pri_grp_rid] = $dn_group; + } + } + } } + } + } else { + $one_entry[$this->_group_attribute][]="CN=Domain Users,CN=Users,".$this->_base_dn; + $add_primary_group = TRUE; + } - if ($add_primary_group) { - @$one_entry[$this->_group_attribute]["count"]++; + if ($add_primary_group) { + @$one_entry[$this->_group_attribute]["count"]++; + } + + if ((1 == $this->_ldap_server_type) && ( '' != $groups_filtering)) { // Active Directory (but not legacy) + // Add the nested groups of the user + $filter = "(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=".$one_entry[$this->_cn_identifier][0].")".$groups_filtering.")"; + $internal_fields = array("cn"); + $group_array = array(); + // SysCo/al added ldap_search error handling, looking for a specific info, no paging needed + if (FALSE !== ($sr = @ldap_search($this->_conn, $this->_base_dn, $filter, $internal_fields))) { + $group_entries = $this->rCountRemover(ldap_get_entries($this->_conn, $sr)); + foreach ($group_entries as $group_entry) { + $group_array[] = $group_entry['cn'][0]; } - - if ((1 == $this->_ldap_server_type) && ( '' != $groups_filtering)) { // Active Directory (but not legacy) - // Add the nested groups of the user - $filter = "(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=".$one_entry[$this->_cn_identifier][0].")".$groups_filtering.")"; - $internal_fields = array("cn"); - $group_array = array(); - // SysCo/al added ldap_search error handling - if (FALSE !== ($sr = @ldap_search($this->_conn,$this->_base_dn,$filter, $internal_fields))) { - $group_entries = $this->rCountRemover(ldap_get_entries($this->_conn, $sr)); - foreach ($group_entries as $group_entry) { - $group_array[] = $group_entry['cn'][0]; - } - } - foreach($group_array as $one_group) { - $add_it = TRUE; - foreach($this->nice_names($one_entry[$this->_group_attribute]) as $level_one_group) { - if (strpos($one_group, $level_one_group) !== FALSE) { - $add_it = FALSE; - } - } - if ($add_it) { - $one_entry[$this->_group_attribute][] = $one_group; - @$one_entry[$this->_group_attribute]["count"]++; - } + } + foreach($group_array as $one_group) { + $add_it = TRUE; + foreach($this->nice_names($one_entry[$this->_group_attribute]) as $level_one_group) { + if (strpos($one_group, $level_one_group) !== FALSE) { + $add_it = FALSE; + } + } + if ($add_it) { + $one_entry[$this->_group_attribute][] = $one_group; + @$one_entry[$this->_group_attribute]["count"]++; + } + } + + // Adding all implicit groups if needed + foreach($in_groups_filtering as $one_group_filtering) { + $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$one_entry[$this->_cn_identifier][0].")".$one_group_filtering['distinguishedname'].")"; + $internal_fields = array("cn"); + // SysCo/al added ldap_search error handling, no paging needed + if (FALSE !== ($sr = @ldap_search($this->_conn, $this->_base_dn, $filter, $internal_fields))) { + if (ldap_count_entries($this->_conn, $sr) > 0) { + $add_it = TRUE; + foreach($this->nice_names($one_entry[$this->_group_attribute]) as $level_one_group) { + if (strpos($one_group_filtering['name'], $level_one_group) !== FALSE) { + $add_it = FALSE; + } } - - // Adding all implicit groups if needed - foreach($in_groups_filtering as $one_group_filtering) { - $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$one_entry[$this->_cn_identifier][0].")".$one_group_filtering['distinguishedname'].")"; - $internal_fields = array("cn"); - // SysCo/al added ldap_search error handling - if (FALSE !== ($sr = @ldap_search($this->_conn,$this->_base_dn,$filter, $internal_fields))) { - if (ldap_count_entries($this->_conn, $sr) > 0) { - $add_it = TRUE; - foreach($this->nice_names($one_entry[$this->_group_attribute]) as $level_one_group) { - if (strpos($one_group_filtering['name'], $level_one_group) !== FALSE) { - $add_it = FALSE; - } - } - if ($add_it) { - $one_entry[$this->_group_attribute][] = $one_group_filtering['name']; - @$one_entry[$this->_group_attribute]["count"]++; - } - } - } + if ($add_it) { + $one_entry[$this->_group_attribute][] = $one_group_filtering['name']; + @$one_entry[$this->_group_attribute]["count"]++; } + } } - } - return ($one_entry); + } + } + } + return ($one_entry); } @@ -1067,7 +1171,8 @@ function user_info($username,$fields=NULL){ $filter = "(&(".$this->_cn_identifier."=".$username."))"; if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","gecos","telephonenumber","primarygroupid"); } - $sr=ldap_search($this->_conn,$this->_users_dn,$filter,$fields); + // No paging implemented here, it's a specific object, no paging needed + $sr=ldap_search($this->_conn, $this->_users_dn, $filter, $fields); $entries = $this->ldap_get_entries_raw($sr); // AD does not return the primary group in the ldap query, we may need to fudge it @@ -1086,6 +1191,7 @@ function user_info($username,$fields=NULL){ if (isset($data[0]["objectsid"][0])) { $domain_sid = $data[0]["objectsid"][0]; $domain_sid_s = sid2str($domain_sid); + // No paging implemented here, it's a specific object, no paging needed $r = ldap_search($this->_conn, $this->_base_dn, "objectSid=".$domain_sid_s."-".$pri_grp_rid, array("distinguishedname")) or exit(); $data = ldap_get_entries($this->_conn, $r); if (isset($data[0]["distinguishedname"][0])) { @@ -1159,67 +1265,70 @@ function user_modify($username,$attributes){ } // Set the password of a user - function user_password($username,$password){ - if ($username==NULL){ return (false); } - if ($password==NULL){ return (false); } - if (!$this->_bind){ return (false); } - if (!$this->_use_ssl){ echo ("FATAL: SSL must be configured on your webserver and enabled in the class to set passwords."); exit(); } - - $user=$this->user_info($username,array("cn")); - if ($user[0]["dn"]==NULL){ return (false); } - $user_dn=$user[0]["dn"]; - - $add=array(); - $add["unicodePwd"][0]=$this->encode_password($password); - - $result=ldap_mod_replace($this->_conn,$user_dn,$add); - if ($result==false){ return (false); } - - return (true); + function user_password($username,$password) { + if ($username==NULL){ return (false); } + if ($password==NULL){ return (false); } + if (!$this->_bind){ return (false); } + if (!$this->_use_ssl){ echo ("FATAL: SSL must be configured on your webserver and enabled in the class to set passwords."); exit(); } + + $user=$this->user_info($username,array("cn")); + if ($user[0]["dn"]==NULL){ return (false); } + $user_dn=$user[0]["dn"]; + + $add=array(); + $add["unicodePwd"][0]=$this->encode_password($password); + + $result=ldap_mod_replace($this->_conn,$user_dn,$add); + if ($result==false){ return (false); } + + return (true); } //***************************************************************************************************************** // COMPUTER FUNCTIONS // Returns an array of information for a specific computer - function computer_info($computer_name,$fields=NULL){ - if ($computer_name==NULL){ return (false); } - if (!$this->_bind){ return (false); } + function computer_info($computer_name,$fields=NULL) { + if ($computer_name==NULL){ return (false); } + if (!$this->_bind){ return (false); } - $filter="(&(objectClass=computer)(cn=".$computer_name."))"; - if ($fields==NULL){ $fields=array($this->_group_attribute,"cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion"); } - $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); - $entries = $this->ldap_get_entries_raw($sr); - - return ($entries); + $filter="(&(objectClass=computer)(cn=".$computer_name."))"; + if ($fields==NULL) { + $fields=array($this->_group_attribute,"cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion"); + } + // No paging implemented here, it's a specific object, no paging needed + $sr = ldap_search($this->_conn,$this->_base_dn,$filter,$fields); + $entries = $this->ldap_get_entries_raw($sr); + + return ($entries); } // Returns all AD users - function all_users($include_desc = false, $search = "*", $sorted = true){ - if (!$this->_bind){ - return (false); - } - - //perform the search and grab all their details - $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=".$search."))"; - $fields=array($this->_cn_identifier,"displayname"); - $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); - $entries = $this->ldap_get_entries_raw($sr); - - $users_array = array(); - for ($i=0; $i<$entries["count"]; $i++){ - if ($include_desc && strlen($entries[$i]["displayname"][0])>0){ - $users_array[ $entries[$i][$this->_cn_identifier][0] ] = $entries[$i]["displayname"][0]; - } elseif ($include_desc){ - $users_array[ $entries[$i][$this->_cn_identifier][0] ] = $entries[$i][$this->_cn_identifier][0]; - } else { - array_push($users_array, $entries[$i][$this->_cn_identifier][0]); - } + function all_users($include_desc = false, $search = "*", $sorted = true) { + if (!$this->_bind){ + return (false); + } + //perform the search and grab all their details + $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=".$search."))"; + $fields = array($this->_cn_identifier,"displayname"); + $sr = ldap_search($this->_conn, $this->_base_dn, $filter, $fields); + $entries = $this->ldap_get_entries_raw($sr); + + $users_array = array(); + for ($i=0; $i<$entries["count"]; $i++){ + if ($include_desc && strlen($entries[$i]["displayname"][0])>0){ + $users_array[ $entries[$i][$this->_cn_identifier][0] ] = $entries[$i]["displayname"][0]; + } elseif ($include_desc){ + $users_array[ $entries[$i][$this->_cn_identifier][0] ] = $entries[$i][$this->_cn_identifier][0]; + } else { + array_push($users_array, $entries[$i][$this->_cn_identifier][0]); } - if ($sorted){ asort($users_array); } - return ($users_array); + } + if ($sorted){ asort($users_array); } + return ($users_array); } + // Returns a complete list of the groups in AD // New implementation 2014-07-22 by SysCo/al (with paging support) function all_groups($include_desc = false, @@ -1228,126 +1337,141 @@ function all_groups($include_desc = false, $local_group = FALSE // $local_group switch added by SysCo/al ) { - $this->_warning_message = ""; - if (!$this->_bind){ return (false); } + $this->_warning_message = ""; + if (!$this->_bind) { + return (false); + } - if ((2 == $this->_ldap_server_type) || (4 == $this->_ldap_server_type)) { // Generic LDAP or eDirectory - $filter="(|(objectClass=posixGroup)(objectClass=groupofNames))"; - $fields=array($this->_group_cn_identifier,"description"); - } else { // Active Directory - //perform the search and grab all their details - if ($local_group) { - $group_account_type = "(|(samaccounttype=".ADLDAP_SECURITY_LOCAL_GROUP.")(samaccounttype=". ADLDAP_SECURITY_GLOBAL_GROUP."))"; - } else { - $group_account_type = "(samaccounttype=".ADLDAP_SECURITY_GLOBAL_GROUP.")"; - } - $filter = "(&(objectCategory=group)".$group_account_type."(cn=".$search."))"; - $fields = array($this->_group_cn_identifier,"description"); + if ((2 == $this->_ldap_server_type) || (4 == $this->_ldap_server_type)) { // Generic LDAP or eDirectory + $filter="(|(objectClass=posixGroup)(objectClass=groupofNames))"; + $fields=array($this->_group_cn_identifier,"description"); + } else { // Active Directory + //perform the search and grab all their details + if ($local_group) { + $group_account_type = "(|(samaccounttype=".ADLDAP_SECURITY_LOCAL_GROUP.")(samaccounttype=". ADLDAP_SECURITY_GLOBAL_GROUP."))"; + } else { + $group_account_type = "(samaccounttype=".ADLDAP_SECURITY_GLOBAL_GROUP.")"; } + $filter = "(&(objectCategory=group)".$group_account_type."(cn=".$search."))"; + $fields = array($this->_group_cn_identifier,"description"); + } - $groups_array = array(); + $groups_array = array(); - $pageSize = 1000; - $page_cookie = ''; - do { - if (function_exists('ldap_control_paged_result')) { - ldap_control_paged_result($this->_conn, $pageSize, false, $page_cookie); - } - $sr = @ldap_search($this->_conn,$this->_base_dn,$filter,$fields); - - if ((!function_exists('ldap_control_paged_result')) && (4 == ldap_errno($this->_conn))) { - $cr = @ldap_count_entries($this->_conn,$sr); - $this->_warning_message = "LDAP server cannot return more than $cr records."; - } - - $entries = $this->ldap_get_entries_raw($sr); - - for ($i=0; $i<$entries["count"]; $i++){ - if ($include_desc && strlen($entries[$i]["description"][0]) > 0 ){ - $groups_array[ $entries[$i][$this->_group_cn_identifier][0] ] = $entries[$i]["description"][0]; - } elseif ($include_desc){ - if (isset($entries[$i][$this->_group_cn_identifier][0])) { - $groups_array[ $entries[$i][$this->_group_cn_identifier][0] ] = $entries[$i][$this->_group_cn_identifier][0]; - } - } else { - if (isset($entries[$i][$this->_group_cn_identifier][0])) { - array_push($groups_array, $entries[$i][$this->_group_cn_identifier][0]); - } - } + $paging_cookie = ''; + do { // LDAP pagination loop + if ($this->_paging_legacy) { + ldap_control_paged_result($this->_conn, $this->_paging_size, false, $paging_cookie); + } + + // New paging support for PHP 7.3+ + if ($this->_paging_ldap_control) { + $sr = @ldap_search($this->_conn, $this->_base_dn, $filter, $fields, + 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => $this->_paging_size, 'cookie' => $paging_cookie]]]); + ldap_parse_result($this->_conn, $sr, $error_code , $matched_dn , $error_message , $referrals, $controls); + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + $paging_cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $paging_cookie = ''; + } + } else { + $sr = @ldap_search($this->_conn, $this->_base_dn, $filter, $fields); + } + + if (4 == ldap_errno($this->_conn)) { // 4 = LDAP_SIZELIMIT_EXCEEDED + $cr = @ldap_count_entries($this->_conn,$sr); + $this->_warning_message = "LDAP server cannot return more than $cr records."; + } + + $entries = $this->ldap_get_entries_raw($sr); + + for ($i=0; $i<$entries["count"]; $i++){ + if ($include_desc && strlen($entries[$i]["description"][0]) > 0 ) { + $groups_array[ $entries[$i][$this->_group_cn_identifier][0] ] = $entries[$i]["description"][0]; + } elseif ($include_desc){ + if (isset($entries[$i][$this->_group_cn_identifier][0])) { + $groups_array[ $entries[$i][$this->_group_cn_identifier][0] ] = $entries[$i][$this->_group_cn_identifier][0]; } - if (function_exists('ldap_control_paged_result_response')) { - ldap_control_paged_result_response($this->_conn, $sr, $page_cookie); + } else { + if (isset($entries[$i][$this->_group_cn_identifier][0])) { + array_push($groups_array, $entries[$i][$this->_group_cn_identifier][0]); } + } } - while($page_cookie !== null && $page_cookie != ''); - - if (function_exists('ldap_control_paged_result')) { - // Reset LDAP paged result - ldap_control_paged_result($this->_conn, $pageSize, false); - } - - if( $sorted ){ - asort($groups_array); + if ($this->_paging_legacy) { + ldap_control_paged_result_response($this->_conn, $sr, $paging_cookie); } - - return ($groups_array); - + } while(($paging_cookie !== null) && ($paging_cookie != '')); + // LDAP pagination loop + + if ($this->_paging_legacy) { + // Reset LDAP paged result + ldap_control_paged_result($this->_conn, $this->_paging_size, false); + } + + if( $sorted ){ + asort($groups_array); + } + + return ($groups_array); + } //************************************************************************************************************ // UTILITY FUNCTIONS (not intended to be called directly but I suppose you could?) - function adldap_schema($attributes){ - - //ldap doesn't like NULL attributes, only set them if they have values - // I'd like to know how to set an LDAP attribute to NULL though, at the moment I set it to a space - // SysCo/al added "mobile" - $mod=array(); - if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; } - if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; } - //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes? - if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; } - if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; } - if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; } - if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; } - if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; } - if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; } - if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; } - if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; } - if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; } - if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; } - if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format? - if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; } - if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; } - if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; } - if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; } - if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; } - if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; } //UNTESTED ***Use DistinguishedName*** - if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; } - if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->encode_password($attributes["password"]); } - if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; } - if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; } - if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; } - if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; } - if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; } - if ($attributes["mobile"]){ $mod["telephoneNumber"][0]=$attributes["mobile"]; } - if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; } - //echo ("
"); print_r($mod);
-    /*
-        // modifying a name is a bit fiddly
-        if ($attributes["firstname"] && $attributes["surname"]){
-            $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
-            $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
-            $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
-        }
-    */
+    function adldap_schema($attributes) {
+
+      //ldap doesn't like NULL attributes, only set them if they have values
+      // I'd like to know how to set an LDAP attribute to NULL though, at the moment I set it to a space
+      // SysCo/al added "mobile"
+      $mod = array();
+      if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; }
+      if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; }
+      //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes?
+      if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; }
+      if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; }
+      if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; }
+      if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; }
+      if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; }
+      if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; }
+      if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; }
+      if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; }
+      if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; }
+      if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; }
+      if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format?
+      if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; }
+      if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; }
+      if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; }
+      if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; }
+      if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; }
+      if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; }  //UNTESTED ***Use DistinguishedName***
+      if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; }
+      if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->encode_password($attributes["password"]); }
+      if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; }
+      if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; }
+      if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; }
+      if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; }
+      if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; }
+      if ($attributes["mobile"]){ $mod["telephoneNumber"][0]=$attributes["mobile"]; }
+      if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; }
+      //echo ("
"); print_r($mod);
+  /*
+      // modifying a name is a bit fiddly
+      if ($attributes["firstname"] && $attributes["surname"]){
+          $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
+          $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
+          $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
+      }
+  */
 
 
-        if (count($mod)==0){
-            return (false);
-        }
-        return ($mod);
+      if (count($mod)==0) {
+        return (false);
+      }
+      return ($mod);
     }
 
 
@@ -1364,7 +1488,7 @@ function group_cn($gid, $cache_only = FALSE, $local_group = FALSE){
         $r=false;
         $r_data = FALSE;
 
-		if ($this->_cache_support) {
+        if ($this->_cache_support) {
             if ("" != $this->get_cache_folder()) {
                 if (file_exists($this->get_cache_folder()."ldap_cgroup_".md5($gid).".cache")) {
                     if ((filemtime($this->get_cache_folder()."ldap_cgroup_".md5($gid).".cache") + $this->get_cache_timeout()) > time()) {
@@ -1381,7 +1505,7 @@ function group_cn($gid, $cache_only = FALSE, $local_group = FALSE){
                 $r_data = TRUE;
             }
         }
-		if (!$r_data) {
+        if (!$r_data) {
             if (!$cache_only) {
                 if ((2 == $this->_ldap_server_type) || (4 == $this->_ldap_server_type)) { // Generic LDAP or eDirectory
                     // http://www.rainingpackets.com/ldap-posixgroup-groupofnames/
@@ -1397,15 +1521,14 @@ function group_cn($gid, $cache_only = FALSE, $local_group = FALSE){
                     $fields=array("primarygrouptoken",$this->_group_cn_identifier,"distinguishedname");
                 }
                 
-                $pageSize = 1000;
-                $page_cookie = '';
-                do {
-                    if (function_exists('ldap_control_paged_result')) {
-                        ldap_control_paged_result($this->_conn, $pageSize, false, $page_cookie);
+                $paging_cookie = '';
+                do { // LDAP pagination loop
+                    if ($this->_paging_legacy) {
+                      ldap_control_paged_result($this->_conn, $this->_paging_size, false, $paging_cookie);
                     }
                     $sr = @ldap_search($this->_conn,$this->_base_dn,$filter,$fields);
                 
-                    if ((!function_exists('ldap_control_paged_result')) && (4 == ldap_errno($this->_conn))) {
+                    if (4 == ldap_errno($this->_conn)) { // 4 = LDAP_SIZELIMIT_EXCEEDED
                         $cr = @ldap_count_entries($this->_conn,$sr);
                         $this->_warning_message = "LDAP server cannot return more than $cr records.";
                     }
@@ -1446,19 +1569,17 @@ function group_cn($gid, $cache_only = FALSE, $local_group = FALSE){
                             $i=$entries["count"];
                         }
                     }
-                    if (function_exists('ldap_control_paged_result_response'))
-                    {
-                        ldap_control_paged_result_response($this->_conn, $sr, $page_cookie);
+                    if ($this->_paging_legacy) {
+                      ldap_control_paged_result_response($this->_conn, $sr, $paging_cookie);
                     }
-                }
-                while($page_cookie !== null && $page_cookie != '');
+                } while(($paging_cookie !== null) && ($paging_cookie != ''));
+                // LDAP pagination loop
                 
-                if (function_exists('ldap_control_paged_result'))
-                {
-                    // Reset LDAP paged result
-                    ldap_control_paged_result($this->_conn, $pageSize, false);
+                if ($this->_paging_legacy) {
+                  // Reset LDAP paged result
+                  ldap_control_paged_result($this->_conn, $this->_paging_size, false);
                 }
-    		}
+            }
         }
         return ($r);
     }
diff --git a/contrib/MultiotpSms.php b/contrib/MultiotpSms.php
index f943259..ff45cb8 100644
--- a/contrib/MultiotpSms.php
+++ b/contrib/MultiotpSms.php
@@ -6,8 +6,8 @@ class MultiotpSms
  * @brief     SMS message using any SMS Provider.
  *
  * @author    Andre Liechti, SysCo systemes de communication sa, 
- * @version   5.8.6.0
- * @date      2022-04-11
+ * @version   5.9.5.4
+ * @date      2022-12-31
  * @since     2018-10-09
  *
  * Predefined providers:
@@ -70,6 +70,9 @@ class MultiotpSms
  *
  * Change Log
  *
+ *   2022-12-26 5.9.5.3 SysCo/al Updated eCall API
+ *                               Updated ASPSMS API
+ *                               Enhanced payload handling
  *   2022-04-11 5.8.6.0 SysCo/al Adding telnyx provider
  *                               Adding specific header option
  *                               Adding international format request
@@ -243,7 +246,7 @@ function setProvider($provider)
                 $this->header = "";
                 break;
             case 'aspsms':
-                $this->url = "http://xml1.aspsms.com:5061/xmlsvr.asp http://xml1.aspsms.com:5098/xmlsvr.asp http://xml2.aspsms.com:5061/xmlsvr.asp http://xml2.aspsms.com:5098/xmlsvr.asp";
+                $this->url = "https://xml3.aspsms.com/xmlsvr.asp https://xml4.aspsms.com/xmlsvr.asp";
                 $this->send_template = "\r\n".
                                        "\r\n".
                                        "  %user\r\n".
@@ -261,13 +264,11 @@ function setProvider($provider)
                 $this->status_success = "20";
                 $this->content_success = "1";
                 $this->no_double_zero = FALSE;
-                $this->international_format = FALSE;
                 $this->basic_auth = FALSE;
                 $this->content_encoding = "HTML";
-                $this->header = "";
                 break;
             case 'aspsms-ucs2':
-                $this->url = "http://xml1.aspsms.com:5061/xmlsvr.asp http://xml1.aspsms.com:5098/xmlsvr.asp http://xml2.aspsms.com:5061/xmlsvr.asp http://xml2.aspsms.com:5098/xmlsvr.asp";
+                $this->url = "https://xml3.aspsms.com/xmlsvr.asp https://xml4.aspsms.com/xmlsvr.asp";
                 $this->send_template = "\r\n".
                                        "\r\n".
                                        "  %user\r\n".
@@ -327,17 +328,16 @@ function setProvider($provider)
                 $this->header = "";
                 break;
             case 'ecall':
-                $this->url = "https://www1.ecall.ch/ecallurl/ecallurl.ASP https://www2.ecall.ch/ecallurl/ecallurl.ASP";
-                $this->send_template = "WCI=Interface&Function=SendPage&AccountName=%user&AccountPassword=%pass&CallBack=%from&Address=%to&Message=%msg";
-                $this->method = "POST";
-                $this->encoding = "ISO";
+                $this->url = "https://url.ecall.ch/api/sms?username=%user&password=%pass&address=%to&message=%msg";
+                $this->send_template = "";
+                $this->method = "GET";
+                $this->encoding = "UTF";
                 $this->status_success = "20";
                 $this->content_success = "0";
-                $this->no_double_zero = TRUE;
+                $this->no_double_zero = FALSE;
                 $this->international_format = FALSE;
                 $this->basic_auth = FALSE;
                 $this->content_encoding = "URL";
-                $this->encode_ampersand = TRUE;
                 $this->header = "";
                 break;
             case 'intellisms':
@@ -828,11 +828,15 @@ function sendSMS($msg = "")
                 $output.= "Content-Length: ".strlen($payload)."\r\n";
                 $output.= "User-Agent: multiOTP SMS\r\n";
                 $output.= "Host: ".$host."\r\n";
+
                 $output.= "\r\n";
-                $output.= $payload;
-                $output.= "\r\n";
-                fputs($fp, $output);
 
+                if (0 != strlen($payload)) {
+                  $output.= $payload;
+                  $output.= "\r\n";
+                }
+
+                fputs($fp, $output);
                 $stream_timeout = $this->timeout;
                 stream_set_blocking($fp, TRUE);
                 stream_set_timeout($fp, $stream_timeout);
@@ -894,16 +898,20 @@ function sendSMS($msg = "")
 
             if (TRUE == $this->debug) {
                 echo "DEBUG payload: $payload
\n)"; - echo "DEBUG reply_status : ".$this->reply_status."\n
"; - echo "DEBUG reply_content : ".$this->reply_content."\n
"; - echo "DEBUG status_success : ".$this->status_success."\n
"; - echo "DEBUG content_success : ".$this->content_success."\n
"; + echo "DEBUG reply_status : ".$this->reply_status."
\n"; + echo "DEBUG reply_content : ".$this->reply_content."
\n"; + echo "DEBUG status_success : ".$this->status_success."
\n"; + echo "DEBUG content_success : ".$this->content_success."
\n"; } if ($result) { return $result; } } + if (TRUE == $this->debug) { + echo "DEBUG result_status: " . ($result_status ? "TRUE" : "FALSE") . "
\n)"; + echo "DEBUG result_content: " . ($result_content ? "TRUE" : "FALSE") . "
\n)"; + } return $result; } } diff --git a/contrib/MultiotpTools.php b/contrib/MultiotpTools.php index 7938d1e..2c8cc6b 100644 --- a/contrib/MultiotpTools.php +++ b/contrib/MultiotpTools.php @@ -18,58 +18,75 @@ } -if (!function_exists('fnmatch')) { +if (!function_exists('nullable_trim')) { + function nullable_trim($string) { + return (is_null($string) ? "" : trim($string)); + } +} + + +if (!function_exists('nullable_bin2hex')) { + function nullable_bin2hex($string) { + return (is_null($string) ? "" : bin2hex($string)); + } +} + + +if (!function_exists('pcre_fnmatch')) { + function pcre_fnmatch($pattern, $string, $flags = 0) { define('FNM_PATHNAME', 1); define('FNM_NOESCAPE', 2); define('FNM_PERIOD', 4); define('FNM_CASEFOLD', 16); - - function fnmatch($pattern, $string, $flags = 0) { - return pcre_fnmatch($pattern, $string, $flags); - } -} -function pcre_fnmatch($pattern, $string, $flags = 0) { $modifiers = null; $transforms = array( - '\*' => '.*', - '\?' => '.', - '\[\!' => '[^', - '\[' => '[', - '\]' => ']', - '\.' => '\.', - '\\' => '\\\\' + '\*' => '.*', + '\?' => '.', + '\[\!' => '[^', + '\[' => '[', + '\]' => ']', + '\.' => '\.', + '\\' => '\\\\' ); // Forward slash in string must be in pattern: if ($flags & FNM_PATHNAME) { - $transforms['\*'] = '[^/]*'; + $transforms['\*'] = '[^/]*'; } // Back slash should not be escaped: if ($flags & FNM_NOESCAPE) { - unset($transforms['\\']); + unset($transforms['\\']); } // Perform case insensitive match: if ($flags & FNM_CASEFOLD) { - $modifiers .= 'i'; + $modifiers .= 'i'; } // Period at start must be the same as pattern: if ($flags & FNM_PERIOD) { - if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) return false; + if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) return false; } $pattern = '#^' - . strtr(preg_quote($pattern, '#'), $transforms) - . '$#' - . $modifiers; + . strtr(preg_quote($pattern, '#'), $transforms) + . '$#' + . $modifiers; return (boolean)preg_match($pattern, $string); + } } +if (!function_exists('fnmatch')) { + function fnmatch($pattern, $string, $flags = 0) { + return pcre_fnmatch($pattern, $string, $flags); + } +} + + /*********************************************************************** * Name: ram_total_space * Short description: return total RAM in Bytes. @@ -605,11 +622,15 @@ function base32_decode($input) $x = ""; if(!in_array($input[$i], $map)) return false; for($j=0; $j < 8; $j++) { - $x .= str_pad(base_convert(@$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT); + if (!is_null(@$flippedMap[@$input[$i + $j]])) { + $x .= str_pad(base_convert(@$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT); + } } $eightBits = str_split($x, 8); for($z = 0; $z < count($eightBits); $z++) { - $binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:""; + if (!is_null($eightBits[$z])) { + $binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:""; + } } } return substr($binaryString, 0, $result_length); @@ -646,12 +667,9 @@ function encode_utf8_if_needed( $a = pack("H*", base_convert($char, 8, 16)); $text = preg_replace('#(\\\\)'.$char.'#',$a,$text); } - $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); + $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1, WINDOWS-1252'); if ("UTF-8" != $encoding) { - $text = utf8_encode($text); - // $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1, WINDOWS-1252'); - // if ("UTF-8" != $encoding) { - // $text = mb_convert_encoding($text, "UTF-8", "UTF-8, ISO-8859-1, WINDOWS-1252"); + $text = mb_convert_encoding($text, "UTF-8", "UTF-8, ISO-8859-1, WINDOWS-1252"); } return $text; } @@ -667,12 +685,9 @@ function encode_utf8_if_needed( function decode_utf8_if_needed($data) { $text = $data; - $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); - if ("UTF-8" == $encoding) { - $text = utf8_decode($text); - // $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1, WINDOWS-1252'); - // if ("ISO-8859-1" != $encoding) { - // $text = mb_convert_encoding($text, "ISO-8859-1", "UTF-8, ISO-8859-1, WINDOWS-1252"); + $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1, WINDOWS-1252'); + if ("UTF-8" == $encoding) { + $text = mb_convert_encoding($text, "ISO-8859-1", "UTF-8, ISO-8859-1, WINDOWS-1252"); } return $text; } @@ -1015,7 +1030,7 @@ function html2text($value) $Document = str_replace('*CRLF*',chr(13).chr(10),$Document); $Document = preg_replace('@[\r\n][ ]+@', chr(13).chr(10), $Document); $Document = preg_replace('@[\r\n][\r\n]+@', chr(13).chr(10).chr(13).chr(10), $Document); - return trim($Document); + return nullable_trim($Document); } } @@ -1147,4 +1162,5 @@ function mask2cidr($mask) { return $bits; } } + ?> \ No newline at end of file diff --git a/contrib/MultiotpXmlParser.php b/contrib/MultiotpXmlParser.php index bce15f8..8796c7c 100644 --- a/contrib/MultiotpXmlParser.php +++ b/contrib/MultiotpXmlParser.php @@ -234,6 +234,9 @@ function CharacterData($parser, $data) * * Name: MultiotpXMLTag (original name: XMLTag) */ + +// PHP >=8.1 specific attribute to allow dynamic properties +#[AllowDynamicProperties] class MultiotpXMLTag { /** diff --git a/contrib/Random.php b/contrib/Random.php index 3b864cb..a7e1296 100644 --- a/contrib/Random.php +++ b/contrib/Random.php @@ -67,6 +67,10 @@ */ function crypt_random_string($length) { + // Added by SysCo/al 2023-01-19 for PHP >=7.1.0 support + if (function_exists('random_bytes')) { + return random_bytes($length); + } if (CRYPT_RANDOM_IS_WINDOWS) { // method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) { diff --git a/contrib/Rijndael.php b/contrib/Rijndael.php index 6474726..b38cec2 100644 --- a/contrib/Rijndael.php +++ b/contrib/Rijndael.php @@ -127,6 +127,9 @@ */ class Crypt_Rijndael extends Crypt_Base { + // PHP >= 8.1 + var $key_size = 0; + /** * The namespace used by the cipher for its constants. * diff --git a/launcher/ReadMe.txt b/launcher/ReadMe.txt index 9bc6ff3..788b649 100644 --- a/launcher/ReadMe.txt +++ b/launcher/ReadMe.txt @@ -15,15 +15,15 @@ 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.5.1 -@date 2022-11-11 +@version 5.9.5.5 +@date 2023-01-19 @since 2016-12-08 -@copyright (c) 2010-2022 SysCo systemes de communication sa +@copyright (c) 2010-2023 SysCo systemes de communication sa @copyright GNU Lesser General Public License LICENCE -Copyright (c) 2010-2022 SysCo systemes de communication sa +Copyright (c) 2010-2023 SysCo systemes de communication sa SysCo (tm) is a trademark of SysCo systemes de communication sa (http://www.sysco.ch) All rights reserved. diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp index dbf7a5d..ebe8bec 100644 --- a/launcher/launcher.cpp +++ b/launcher/launcher.cpp @@ -14,17 +14,17 @@ * and run multiotp.windows.php with the provided arguments. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.5.1 - * @date 2022-11-11 + * @version 5.9.5.5 + * @date 2023-01-19 * @since 2016-12-08 - * @copyright (c) 2010-2022 SysCo systemes de communication sa + * @copyright (c) 2010-2023 SysCo systemes de communication sa * @copyright GNU Lesser General Public License * *//* * * LICENCE * - * Copyright (c) 2010-2022 SysCo systemes de communication sa + * Copyright (c) 2010-2023 SysCo systemes de communication sa * SysCo (tm) is a trademark of SysCo systemes de communication sa * (http://www.sysco.ch) * All rights reserved. @@ -68,8 +68,8 @@ #include #define SOFTWARE "LAUNCHPHPMULTIOTP" -#define VER_NUMBER "5.9.5.1" -#define VER_DATE "2022-11-11" +#define VER_NUMBER "5.9.5.5" +#define VER_DATE "2023-01-19" 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 846974c..298ed7a 100644 --- a/multiotp.class.php +++ b/multiotp.class.php @@ -69,20 +69,20 @@ * * The Readme file contains additional information. * - * PHP 5.3.0 or higher is supported. + * PHP 5.4.0 or higher is supported. * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.5.1 - * @date 2022-11-11 + * @version 5.9.5.5 + * @date 2023-01-19 * @since 2010-06-08 - * @copyright (c) 2010-2022 SysCo systemes de communication sa + * @copyright (c) 2010-2023 SysCo systemes de communication sa * @copyright GNU Lesser General Public License * *//* * * LICENCE * - * Copyright (c) 2010-2022 SysCo systemes de communication sa + * Copyright (c) 2010-2023 SysCo systemes de communication sa * SysCo (tm) is a trademark of SysCo systemes de communication sa * (http://www.sysco.ch/) * All rights reserved. @@ -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.5.1 - * @date 2022-11-11 + * @version 5.9.5.5 + * @date 2023-01-19 * @since 2010-07-18 */ { @@ -364,7 +364,24 @@ class Multiotp var $_ldap_sync_stop_file_name; // AD/LDAP synchronization stop file name var $_last_http_status; // Last HTTP status var $_bad_syslog_server; // The Syslog server is temporarly bad - var $_state; // State provided by the radius client + var $_state; // State provided by the radius client + + // No more dynamic properties with PHP >= 8.2 + var $_sql_tables_schema; + var $_sql_tables_index; + var $_sql_tables_ignore; + var $_sql_tables_not_in_schema; + var $_hash_salt; + var $_random_salt; + var $_encryption_check; + var $_mysql_database_link; + var $_mysqli; + var $_pgsql_database_link; + var $_migration_from_file; + var $_keep_local; + var $_sms_providers_array; + var $_linux_folder_mode; + var $_cache_data; /** * @brief Class constructor. @@ -376,8 +393,8 @@ class Multiotp * @retval void * * @author Andre Liechti, SysCo systemes de communication sa, - * @version 5.9.5.1 - * @date 2022-11-11 + * @version 5.9.5.5 + * @date 2023-01-19 * @since 2010-07-18 */ function __construct( @@ -401,14 +418,14 @@ function __construct( if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { - $temp_version = '@version 5.9.5.1'; // 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)); + $temp_version = '@version 5.9.5.5'; // You should add a suffix for your changes (for example 5.0.3.2-andy-2016-10-XX) + $this->_version = nullable_trim(mb_substr($temp_version, 8)); } if (!isset($this->_date)) { - $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)); + $temp_date = '@date 2023-01-19'; // You should update the date with the date of your changes + $this->_date = nullable_trim(mb_substr($temp_date, 8)); } - if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMiBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } + if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAyMyBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } if (!isset($this->_website)) { $this->_website = base64_decode('aHR0cDovL3d3dy5tdWx0aU9UUC5uZXQ='); } $this->_anonymous_stat_interval = 604800; // Stat interval: 7 * 24 * 60 * 60 = 604800 = 1 week @@ -571,6 +588,7 @@ function __construct( 'ldap_default_algorithm' => "TEXT DEFAULT 'totp'", 'ldap_domain_controllers' => "TEXT DEFAULT ''", // If ldap_group_attribute is empty, the default value used is "memberOf" + 'ldap_filter' => "TEXT DEFAULT ''", 'ldap_group_attribute' => "TEXT DEFAULT ''", // If ldap_group_cn_identifier is empty, the default value used is "cn" 'ldap_group_cn_identifier' => "TEXT DEFAULT ''", @@ -610,7 +628,7 @@ function __construct( 'overwrite_request_ldap_pwd' => "int(1) DEFAULT 1", 'radius_error_reply_message' => "int(1) DEFAULT 1", 'radius_reply_attributor' => "TEXT DEFAULT ' += '", - 'radius_reply_separator_hex' => "TEXT DEFAULT '".bin2hex(',')."'", + 'radius_reply_separator_hex' => "TEXT DEFAULT '".nullable_bin2hex(',')."'", 'radius_tag_prefix' => "TEXT DEFAULT ''", 'scratch_passwords_digits' => "int(10) DEFAULT 6", 'scratch_passwords_amount' => "int(10) DEFAULT 10", @@ -920,7 +938,7 @@ function __construct( } $this->SetBaseDir($current_dir); - if ("" != trim($config_dir)) { + if ("" != nullable_trim($config_dir)) { $this->SetConfigFolder($config_dir, true, false); } @@ -983,7 +1001,7 @@ function __construct( if (("" == $encryption_key) || ('MuLtIoTpEnCrYpTiOn' == $encryption_key) || ('DefaultCliEncryptionKey' == $encryption_key)) { if (("" != $this->GetEncryptionKeyFullPath()) && file_exists($this->GetEncryptionKeyFullPath())) { if ($encryption_key_file_handler = @fopen($this->GetEncryptionKeyFullPath(), "rt")) { - $temp_encryption_key = trim(fgets($encryption_key_file_handler)); + $temp_encryption_key = nullable_trim(fgets($encryption_key_file_handler)); if ("" != $temp_encryption_key) { $this->SetEncryptionKey($temp_encryption_key, false); } @@ -1067,13 +1085,13 @@ function __destruct() function SetRadiusTagPrefix($value) { - $this->_config_data['radius_tag_prefix'] = trim($value); - return trim($value); + $this->_config_data['radius_tag_prefix'] = nullable_trim($value); + return nullable_trim($value); } function GetRadiusTagPrefix() { - return trim($this->_config_data['radius_tag_prefix']); + return nullable_trim($this->_config_data['radius_tag_prefix']); } @@ -1110,7 +1128,7 @@ function SetLdapCacheFolder($value) { if ($this->ConvertToWindowsPathIfNeeded(sys_get_temp_dir()."/") == $value) { $folder = "tempdir"; } - $this->_config_data['ldap_cache_folder'] = trim($folder); + $this->_config_data['ldap_cache_folder'] = nullable_trim($folder); } @@ -1130,8 +1148,8 @@ function IsLdapRecursiveCacheOnly() { function GetLdapCacheFolder() { - $folder = trim($this->_config_data['ldap_cache_folder']); - if (("tempdir" == $folder) || ("" == trim($folder))) { + $folder = nullable_trim($this->_config_data['ldap_cache_folder']); + if (("tempdir" == $folder) || ("" == nullable_trim($folder))) { $folder = $this->ConvertToWindowsPathIfNeeded(sys_get_temp_dir()."/"); } if (file_exists($folder) && touch($folder."test.cache")) { @@ -1261,7 +1279,7 @@ function GetUserDialinIpAddress( if($user != '') { $this->SetUser($user); } - return $this->_user_data['dialin_ip_address']; + return (isset($this->_user_data['dialin_ip_address']) ? $this->_user_data['dialin_ip_address'] : ""); } @@ -1289,7 +1307,7 @@ function GetUserDialinIpMask( if($user != '') { $this->SetUser($user); } - return $this->_user_data['dialin_ip_mask']; + return (isset($this->_user_data['dialin_ip_mask']) ? $this->_user_data['dialin_ip_mask'] : ""); } @@ -1376,49 +1394,49 @@ function GetLastHttpStatus() function SetLockTime($value) { - $this->_lock_time = trim($value); + $this->_lock_time = nullable_trim($value); } function GetLockTime() { - return trim($this->_lock_time); + return nullable_trim($this->_lock_time); } function SetLdapSyncStopFileName($value) { - $this->_ldap_sync_stop_file_name = trim($value); + $this->_ldap_sync_stop_file_name = nullable_trim($value); } function GetLdapSyncStopFileName() { - return trim($this->_ldap_sync_stop_file_name); + return nullable_trim($this->_ldap_sync_stop_file_name); } function SetLdapSyncLockFileName($value) { - $this->_ldap_sync_lock_file_name = trim($value); + $this->_ldap_sync_lock_file_name = nullable_trim($value); } function GetLdapSyncLockFileName() { - return trim($this->_ldap_sync_lock_file_name); + return nullable_trim($this->_ldap_sync_lock_file_name); } function SetLockFolder($value) { - $this->_lock_folder = trim($value); + $this->_lock_folder = nullable_trim($value); } function GetLockFolder() { - return trim($this->_lock_folder); + return nullable_trim($this->_lock_folder); } @@ -1490,13 +1508,13 @@ function GetTouchSuffixArray() function SetTouchFolder($value) { - $this->_touch_folder = trim($value); + $this->_touch_folder = nullable_trim($value); } function GetTouchFolder() { - return trim($this->_touch_folder); + return nullable_trim($this->_touch_folder); } @@ -1551,7 +1569,7 @@ function TouchFolder( $this->WriteLog("Debug: *Touch element $type_fn $item_fn $id_fn", FALSE, FALSE, 8888, 'System', ''); } foreach ($touch_suffix_array as $one_touch_suffix) { - $filename_path = $this->GetTouchFolder().bin2hex($type_fn."\t".$item_fn."\t".$id_fn.(("" != $one_touch_suffix) ? ("\t".$one_touch_suffix) : "")).".sync"; + $filename_path = $this->GetTouchFolder().nullable_bin2hex($type_fn."\t".$item_fn."\t".$id_fn.(("" != $one_touch_suffix) ? ("\t".$one_touch_suffix) : "")).".sync"; $result = touch($filename_path); if ($result && ('' != $this->GetLinuxFileMode())) { @chmod($filename_path, octdec($this->GetLinuxFileMode())); @@ -1581,12 +1599,12 @@ function UserRestoreBeforeWrite() function SetUserLanguage($value) { - $this->_user_data['language'] = trim($value); + $this->_user_data['language'] = nullable_trim($value); } function GetUserLanguage($ignore_main_language = FALSE) { - $language = trim($this->_user_data['language']); + $language = nullable_trim(isset($this->_user_data['language']) ? $this->_user_data['language'] : ""); if (('' == $language) && (TRUE != $ignore_main_language)) { $language = $this->GetLanguage(); } @@ -1595,12 +1613,12 @@ function GetUserLanguage($ignore_main_language = FALSE) { function SetLanguage($value) { - $this->_config_data['language'] = trim($value); + $this->_config_data['language'] = nullable_trim($value); } function GetLanguage() { - return mb_strtolower(trim($this->_config_data['language']),'UTF-8'); + return mb_strtolower(nullable_trim($this->_config_data['language']),'UTF-8'); } @@ -1751,7 +1769,7 @@ function ResetCacheArray() $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -1901,11 +1919,11 @@ function WriteData( $encryption_key = $this->GetEncryptionKey(); } - $item_info = trim($item." ".$id_value); + $item_info = nullable_trim($item." ".$id_value); if ('group' == mb_strtolower($item,'UTF-8')) { - $item_info = trim($item." ".(isset($data_array['name'])?$data_array['name']:$id_value)); + $item_info = nullable_trim($item." ".(isset($data_array['name'])?$data_array['name']:$id_value)); } elseif ('device' == mb_strtolower($item,'UTF-8')) { - $item_info = trim($item." ".(isset($data_array['description'])?$data_array['description']:(isset($data_array['ip_or_fqdn'])?$data_array['ip_or_fqdn']:$id_value))); + $item_info = nullable_trim($item." ".(isset($data_array['description'])?$data_array['description']:(isset($data_array['ip_or_fqdn'])?$data_array['ip_or_fqdn']:$id_value))); } if ('configuration' == mb_strtolower($item,'UTF-8')) { @@ -2040,7 +2058,7 @@ function WriteData( while(!feof($raw_fn)) { $line.= mb_strtolower($key,'UTF-8'); - $value = bin2hex(fread($raw_fn, 40)); + $value = nullable_bin2hex(fread($raw_fn, 40)); if ($encrypt_all || ((!$no_encryption_hash) && ((FALSE !== mb_strpos(mb_strtolower($this->GetAttributesToEncrypt(),'UTF-8'), mb_strtolower('*'.$key.'*','UTF-8'))) || ("*all*" == mb_strtolower($this->GetAttributesToEncrypt(),'UTF-8'))) @@ -2058,7 +2076,7 @@ function WriteData( $value = str_replace(chr(13).chr(10),"<>",$value); $value = str_replace(chr(10),"<>",$value); $value = str_replace(chr(13),"<>",$value); - if ('' != trim($key)) { + if ('' != nullable_trim($key)) { $line.= mb_strtolower($key,'UTF-8'); if ($encrypt_all || ((!$no_encryption_hash) && @@ -2146,7 +2164,7 @@ function WriteData( } if (($in_the_schema) && ($key != $id_field)) { - if (('' == trim($value)) && ("int" == $row_type)) { + if (('' == nullable_trim($value)) && ("int" == $row_type)) { $value = 0; } if (($encrypt_all || @@ -2179,7 +2197,7 @@ function WriteData( if (is_object($this->_mysqli)) { if (!($result = @$this->_mysqli->query($sQuery))) { - $this->WriteLog(array('text' => "Error: SQL query error ".trim($this->_mysqli->error)." ".$sQuery, + $this->WriteLog(array('text' => "Error: SQL query error ".nullable_trim($this->_mysqli->error)." ".$sQuery, 'file_only' => TRUE, 'error_code' => 40, 'category' => 'System', @@ -2189,7 +2207,7 @@ function WriteData( } else { $num_rows = $result->num_rows; } - } elseif (!($result = @mysql_query($sQuery, $this->_mysql_database_link))) { + } elseif ((NULL != $this->_mysql_database_link) && (!($result = @mysql_query($sQuery, $this->_mysql_database_link)))) { $this->WriteLog(array('text' => "Error: SQL query error ($sQuery) : ".mysql_error(), 'file_only' => TRUE, 'error_code' => 40, @@ -2207,17 +2225,46 @@ function WriteData( $sQuery.= " WHERE `$id_field`='".$esc_id_value."'"; } if (is_object($this->_mysqli)) { - if (!($rResult = @$this->_mysqli->query($sQuery))) { - $this->WriteLog(array('text' => "Error: SQL query error ".trim($this->_mysqli->error)." ".$sQuery, - 'file_only' => TRUE, - 'error_code' => 40, - 'category' => 'System', - 'user' => '', - 'overwrite_severity' => 3) - ); - $result = FALSE; + try { + $rResult = @$this->_mysqli->query($sQuery); + // Backward compatibility + if (!$rResult) { + $this->WriteLog(array('text' => "Error: SQL query error ".nullable_trim($this->_mysqli->error)." ".$sQuery, + 'file_only' => TRUE, + 'error_code' => 40, + 'category' => 'System', + 'user' => '', + 'overwrite_severity' => 3) + ); + $result = FALSE; } - } elseif (!($rResult = @mysql_query($sQuery, $this->_mysql_database_link))) { + } + catch(Exception $e) { + $this->WriteLog(array('text' => "Error: SQL query error ".nullable_trim($this->_mysqli->error)." ".$sQuery, + 'file_only' => TRUE, + 'error_code' => 40, + 'category' => 'System', + 'user' => '', + 'overwrite_severity' => 3) + ); + $result = FALSE; + } + } else { + try { + $rResult = @mysql_query($sQuery, $this->_mysql_database_link); + // Backward compatibility + if (!$rResult) { + $this->WriteLog(array('text' => "Error: SQL query error ($sQuery) : ".mysql_error(), + 'file_only' => TRUE, + 'error_code' => 40, + 'category' => 'System', + 'user' => '', + 'overwrite_severity' => 3) + ); + $result = FALSE; + } + } + catch(Exception $e) { $this->WriteLog(array('text' => "Error: SQL query error ($sQuery) : ".mysql_error(), 'file_only' => TRUE, 'error_code' => 40, @@ -2226,6 +2273,7 @@ function WriteData( 'overwrite_severity' => 3) ); $result = FALSE; + } } } else { if ('' != $id_field) { @@ -2235,7 +2283,7 @@ function WriteData( } if (is_object($this->_mysqli)) { if (!($rResult = @$this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: SQL query error ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: SQL query error ".nullable_trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 40, 'System', '', 3); } elseif (0 == $this->_mysqli->affected_rows) { $this->WriteLog("Error: SQL entry for ".$item_info." cannot be created or changed", FALSE, FALSE, 43, 'System', '', 3); $result = FALSE; @@ -2254,8 +2302,8 @@ function WriteData( } } } elseif ((!$backup_format) && ('pgsql' == $this->GetBackendType()) && (!$file_only)) { - $esc_id_value = pg_escape_string($id_value); if ($this->OpenPGSQLDatabase()) { + $esc_id_value = pg_escape_string($this->_pgsql_database_link, $id_value); $result = TRUE; $sQi_Columns = ''; $sQi_Values = ''; @@ -2292,7 +2340,7 @@ function WriteData( } if (($in_the_schema) && ($key != $id_field)) { - if (('' == trim($value)) && ("int" == $row_type)) { + if (('' == nullable_trim($value)) && ("int" == $row_type)) { $value = 0; } if (($encrypt_all || @@ -2304,7 +2352,7 @@ function WriteData( ) { $value = 'ENC:'.$this->Encrypt($key,$value,$encryption_key).':ENC'; } - $value = pg_escape_string($value); + $value = pg_escape_string($this->_pgsql_database_link, $value); $sQu_Data .= "\"{$key}\" = '{$value}',"; // Data for UPDATE query $sQi_Columns .= "\"{$key}\","; // Columns for INSERT query $sQi_Values .= "'{$value}',"; // Values for INSERT query @@ -2319,7 +2367,7 @@ function WriteData( } if (!($result = @pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error($this->_pgsql_database_link), TRUE, FALSE, 40, 'System', '', 3); } else { $num_rows = pg_num_rows($result); } @@ -2330,7 +2378,7 @@ function WriteData( $sQuery.= " WHERE \"".$id_field."\" = '".$esc_id_value."'"; } if (!($rResult = @pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error($this->_pgsql_database_link), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } else { @@ -2340,7 +2388,7 @@ function WriteData( $sQuery = "INSERT INTO \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$table.'_table']."\" (".mb_substr($sQi_Columns,0,-1).") VALUES (".mb_substr($sQi_Values,0,-1).")"; } if (!($rResult = @pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error($this->_pgsql_database_link), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } elseif (0 == pg_affected_rows($rResult)) { $this->WriteLog("Error: SQL entry for ".$item_info." cannot be created or changed", FALSE, FALSE, 43, 'System', '', 3); @@ -2410,12 +2458,12 @@ function ReadCacheData() $cache_filename = 'cache.ini'; // File exists in v3 format only, we don't need any conversion if (file_exists($this->GetCacheFolder().$cache_filename)) { if ($file_handler = @fopen($this->GetCacheFolder().$cache_filename, "rt")) { - $first_line = trim(fgets($file_handler)); + $first_line = nullable_trim(fgets($file_handler)); while (!feof($file_handler)) { $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($file_handler))); $line_array = explode("=",$line,2); - if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) { + if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != nullable_trim($line)) && (isset($line_array[1]))) { if ("" != $line_array[0]) { $this->_cache_data[mb_strtolower($line_array[0],'UTF-8')] = $line_array[1]; } @@ -2439,7 +2487,7 @@ function ReadCacheData() if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: ".nullable_trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = $result->fetch_assoc(); @@ -2484,7 +2532,7 @@ function ReadCacheData() $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: ".pg_last_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); @@ -2551,7 +2599,7 @@ function ResetConfigArray($array_to_reset = '') $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -2572,7 +2620,7 @@ function ResetStatArray($array_to_reset = '') $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -2640,7 +2688,7 @@ function IsAnonymousStatTime() function GetAnonymousStatRandomId() { - $result = trim($this->_config_data['anonymous_stat_random_id']); + $result = nullable_trim($this->_config_data['anonymous_stat_random_id']); if ('' == $result) { $result = mb_substr(md5(date("YmdHis").mt_rand(100000,999999)),0,20).mb_substr(sha1(mt_rand(100000,999999).date("YmdHis")),0,20); $this->_config_data['anonymous_stat_random_id'] = $result; @@ -2791,7 +2839,7 @@ function BackupConfiguration( if (!$bc_array['config_only']) { // Ddns foreach (explode("\t", $this->GetDdnsList()) as $one_ddns) { - if ('' != trim($one_ddns)) { + if ('' != nullable_trim($one_ddns)) { $ddns_array = $this->ReadDdnsData($one_ddns); if ($ddns_array["exists"]) { $content = $this->WriteDdnsData($ddns_array, $one_ddns, $bc_array); @@ -2802,7 +2850,7 @@ function BackupConfiguration( } // Devices foreach (explode("\t", $this->GetDevicesList()) as $one_device) { - if ('' != trim($one_device)) { + if ('' != nullable_trim($one_device)) { if ($this->ReadDeviceData($one_device)) { $content = $this->WriteDeviceData(array_merge($bc_array, array("with_radius_update" => FALSE))); @@ -2813,7 +2861,7 @@ function BackupConfiguration( } // Groups foreach (explode("\t", $this->GetGroupsList()) as $one_group) { - if ('' != trim($one_group)) { + if ('' != nullable_trim($one_group)) { if ($this->ReadGroupData($one_group)) { $content = $this->WriteGroupData($bc_array); $result = $result && ($content !== FALSE); @@ -2823,7 +2871,7 @@ function BackupConfiguration( } // Tokens foreach (explode("\t", $this->GetTokensList()) as $one_token) { - if ('' != trim($one_token)) { + if ('' != nullable_trim($one_token)) { if ($this->ReadTokenData($one_token)) { $content = $this->WriteTokenData($bc_array); $result = $result && ($content !== FALSE); @@ -3145,7 +3193,7 @@ function RestoreConfiguration( $line_array = explode("=",$line,2); $key = isset($line_array[0]) ? $line_array[0] : ''; $value = isset($line_array[1]) ? $line_array[1] : ''; - if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) { + if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != nullable_trim($line)) && (isset($line_array[1]))) { if (":" == mb_substr($key, -1)) { $key = mb_substr($key, 0, mb_strlen($key) -1); $value = $this->Decrypt($key,$value,$restore_key); @@ -3236,7 +3284,7 @@ function IsConsoleAuthentication() function SetLogFileName( $filename ) { - $this->_log_file_name = trim($filename); + $this->_log_file_name = nullable_trim($filename); } @@ -3448,7 +3496,7 @@ function WriteLog( $post_text.= '['.$this->GetCallingMac().'] '; } } - $log_text = trim(trim($pre_text).' '.$text.' '.trim($post_text)); + $log_text = nullable_trim(nullable_trim($pre_text).' '.$text.' '.nullable_trim($post_text)); // Cleaning the log text, just to be sure that we don't have tabs (\t) // in them, and also that the CRLF, CR or LF is the good done (\n) @@ -3474,7 +3522,7 @@ function WriteLog( echo $display_text; } - if (("" != trim($this->GetSysLogServer())) && (!$this->IsSysLogServerBad()) && (!$no_syslog)) { + if (("" != nullable_trim($this->GetSysLogServer())) && (!$this->IsSysLogServerBad()) && (!$no_syslog)) { if ($severity <= $this->GetSyslogLevel()) { $syslog_server = $this->GetSysLogServer(); if (!is_valid_ipv4($syslog_server)) { @@ -3554,7 +3602,7 @@ function WriteLog( if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: SQL query error ($sQuery) : ".trim($this->_mysqli->error), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: SQL query error ($sQuery) : ".nullable_trim($this->_mysqli->error), TRUE, FALSE, 40, 'System', '', 3); } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); @@ -3563,16 +3611,16 @@ function WriteLog( //mysql_close($log_link); } elseif ('pgsql' == $this->GetBackendType()) { if ($this->OpenPGSQLDatabase()) { - $log_severity_escaped = pg_escape_string($severity_txt); - $log_user_escaped = pg_escape_string($user_log); - $log_category_escaped = pg_escape_string($category_log); - $log_text_escaped = pg_escape_string(mb_substr($log_text,0,255)); - $log_create_host = pg_escape_string($this->GetCreateHost()); + $log_severity_escaped = pg_escape_string($this->_pgsql_database_link, $severity_txt); + $log_user_escaped = pg_escape_string($this->_pgsql_database_link, $user_log); + $log_category_escaped = pg_escape_string($this->_pgsql_database_link, $category_log); + $log_text_escaped = pg_escape_string($this->_pgsql_database_link, mb_substr($log_text,0,255)); + $log_create_host = pg_escape_string($this->_pgsql_database_link, $this->GetCreateHost()); $sQuery = "INSERT INTO \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_log_table']."\" (\"datetime\",\"severity\",\"user\",\"category\",\"logentry\",\"local_only\",\"create_host\", \"create_time\") VALUES ('".$log_datetime."','".$log_severity_escaped."','".$log_user_escaped."','".$log_category_escaped."','".$log_text_escaped."',".intval($local_only).",'".$log_create_host."', ".$log_time.")"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error($this->_pgsql_database_link), TRUE, FALSE, 40, 'System', '', 3); } } //pg_close($log_link); @@ -3621,12 +3669,12 @@ function ShowLog( if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: Unable to access the database: ".nullable_trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $rResult->fetch_assoc()) { if ($as_result) { - $result.= trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; + $result.= nullable_trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } } } @@ -3636,7 +3684,7 @@ function ShowLog( } else { while ($aRow = mysql_fetch_assoc($rResult)) { if ($as_result) { - $result.= trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; + $result.= nullable_trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } } } @@ -3647,12 +3695,12 @@ function ShowLog( $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_log_table']."\""; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: Unable to access the database: ".pg_last_error($this->_pgsql_database_link), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = pg_fetch_assoc($rResult)) { if ($as_result) { - $result.= trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; + $result.= nullable_trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } } } @@ -3662,7 +3710,7 @@ function ShowLog( if ($log_file_handle = @fopen($this->GetLogFolder().$this->GetLogFileName(),"r")) { while (!feof($log_file_handle)) { if ($as_result) { - $result.= trim(fgets($log_file_handle))."\n"; + $result.= nullable_trim(fgets($log_file_handle))."\n"; } } fclose($log_file_handle); @@ -3694,7 +3742,7 @@ function ClearLog($days = 0) if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: Unable to access the database: ".nullable_trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { @@ -3713,7 +3761,7 @@ function ClearLog($days = 0) } if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: Unable to access the database: ".pg_last_error($this->_pgsql_database_link), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } } else { @@ -3923,7 +3971,7 @@ function SetEncryptionKeyFullPath( function GetEncryptionKeyFullPath() { - return trim(isset($this->_config_data['encryption_key_full_path'])?$this->_config_data['encryption_key_full_path']:""); + return nullable_trim(isset($this->_config_data['encryption_key_full_path'])?$this->_config_data['encryption_key_full_path']:""); } @@ -3936,7 +3984,7 @@ function SetHashSaltFullPath( function GetHashSaltFullPath() { - return trim($this->_config_data['hash_salt_full_path']); + return nullable_trim($this->_config_data['hash_salt_full_path']); } @@ -4100,7 +4148,7 @@ function GetLocalIpAddress() if (preg_match("/.*IPv4.*[^\.]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})[^\.]+/", $line)) { preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { - $temp = trim($result_array[0][1]); + $temp = nullable_trim($result_array[0][1]); if ('0.0.0.0' != $temp) { $ip = $temp; break; @@ -4142,7 +4190,7 @@ function GetNetworkInfo() $result_array = array(); preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if ((!$fixed_gateway) && (isset($result_array[2][1]))) { - $temp = trim($result_array[2][1]); + $temp = nullable_trim($result_array[2][1]); if ('0.0.0.0' != $temp) { $gateway = $temp; if (!isset($result_array[3][1])) { @@ -4161,7 +4209,7 @@ function GetNetworkInfo() $result_array = array(); preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { - $temp = trim($result_array[0][1]); + $temp = nullable_trim($result_array[0][1]); if ($next_is_mask) { $mask = $temp; $cidr_mask = mask2cidr($mask); @@ -4188,7 +4236,7 @@ function GetNetworkInfo() preg_match_all("/[^\"]+\"([^\"]*)\".*/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { // We receive something back which is probably coded in CP850 - $interface_name = mb_convert_encoding (trim($result_array[0][1]),"UTF-8","CP850"); + $interface_name = mb_convert_encoding (nullable_trim($result_array[0][1]),"UTF-8","CP850"); $mode = "static"; break; } @@ -4200,9 +4248,9 @@ function GetNetworkInfo() $ip4config = false; foreach ($output as $line) { $line.= " "; - if (0 === mb_strpos(trim($line),"pushd interface ipv4")) { + if (0 === mb_strpos(nullable_trim($line),"pushd interface ipv4")) { $ip4config = true; - } elseif ($ip4config && (0 === mb_strpos(trim($line),"popd"))) { + } elseif ($ip4config && (0 === mb_strpos(nullable_trim($line),"popd"))) { $ip4config = false; } if ($ip4config) { @@ -4210,7 +4258,7 @@ function GetNetworkInfo() preg_match_all("/^set interface[^\"]+\"([^\"]*)\".*metric=1.*/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { // We receive something back which is probably coded in CP850 - $interface_name = mb_convert_encoding (trim($result_array[0][1]),"UTF-8","CP850"); + $interface_name = mb_convert_encoding (nullable_trim($result_array[0][1]),"UTF-8","CP850"); break; } } @@ -4226,7 +4274,7 @@ function GetNetworkInfo() $result_array = array(); preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if (($dns_count < 2) && isset($result_array[0][1])) { - $dns[$dns_count] = trim($result_array[0][1]); + $dns[$dns_count] = nullable_trim($result_array[0][1]); $dns_count++; } } @@ -4356,11 +4404,11 @@ function SetNetworkInfo( fwrite($write, "iface eth0 inet dhcp\n"); fwrite($write, "\n"); } - } elseif ((0 === mb_strpos(trim($one_line),"allow-")) || - (0 === mb_strpos(trim($one_line),"auto")) || - (0 === mb_strpos(trim($one_line),"iface")) || - (0 === mb_strpos(trim($one_line),"mapping")) || - (0 === mb_strpos(trim($one_line),"source"))) { + } elseif ((0 === mb_strpos(nullable_trim($one_line),"allow-")) || + (0 === mb_strpos(nullable_trim($one_line),"auto")) || + (0 === mb_strpos(nullable_trim($one_line),"iface")) || + (0 === mb_strpos(nullable_trim($one_line),"mapping")) || + (0 === mb_strpos(nullable_trim($one_line),"source"))) { $direct_write = true; } if ($direct_write) { @@ -4402,7 +4450,7 @@ function GetCreateHost() function GetSystemName() { - $system_name = trim(php_uname('n')); + $system_name = nullable_trim(php_uname('n')); return $system_name; } @@ -4438,7 +4486,7 @@ function GetEmailAdminAddress() function SetHashSalt( $salt ) { - $this->_hash_salt = trim($salt); + $this->_hash_salt = nullable_trim($salt); } @@ -4452,27 +4500,27 @@ function GetHashSalt() ("" != $this->GetHashSaltFullPath()) && file_exists($this->GetHashSaltFullPath())) { if ($hash_salt_file_handler = @fopen($this->GetHashSaltFullPath(), "rt")) { - $temp = trim(fgets($hash_salt_file_handler)); + $temp = nullable_trim(fgets($hash_salt_file_handler)); if ("" != $temp) { $salt = $temp; } fclose($hash_salt_file_handler); } } - return trim($salt); + return nullable_trim($salt); } function SetRandomSalt( $salt ) { - $this->_random_salt = trim($salt); + $this->_random_salt = nullable_trim($salt); } function GetRandomSalt() { - return trim($this->_random_salt); + return nullable_trim($this->_random_salt); } @@ -4771,7 +4819,7 @@ function SetSqlServer( function GetSqlServer() { - return trim($this->_config_data['sql_server']); + return nullable_trim($this->_config_data['sql_server']); } @@ -4823,65 +4871,100 @@ function MySqlAddRowIfNeeded( $result = FALSE; $index_special_suffix = ((mb_strtoupper($column_type, 'UTF-8') == "TEXT") ? "(77)" : ""); if (is_object($this->_mysqli)) { - $sql_query = "SELECT `".$column."` FROM ".$table; - if ($select_row = $this->_mysqli->query($sql_query)) { - $result = TRUE; - $sql_query = "ALTER TABLE ".$table." CHANGE `".$column."` `".$column."` ".$column_type; - if ($column_default != NULL) { - $sql_query.= " DEFAULT ".$column_default; - } - $sql_query_index = "ALTER TABLE ".$table." DROP INDEX `".$column."`;"; - try { $this->_mysqli->query($sql_query_index); } catch(Exception $e) { } - if ($is_an_index) { - $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; - } - if (!$this->_mysqli->query($sql_query)) { - $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); - $result = FALSE; - } - } else { //$select_row = $result->fetch_assoc(); - $sql_query = "ALTER TABLE ".$table." ADD `".$column."` ".$column_type; - if ($column_default != NULL) { - $sql_query.= " DEFAULT ".$column_default; - } - if ($is_an_index) { - $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; - } - if (!$this->_mysqli->query($sql_query)) { - $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); - $result = FALSE; - } + $sql_query = "SELECT `".$column."` FROM ".$table; + try { + $select_row = $this->_mysqli->query($sql_query); + // Backward compatibility + if (!$select_row) { + $sql_query = "ALTER TABLE ".$table." ADD `".$column."` ".$column_type; + if ($column_default != NULL) { + $sql_query.= " DEFAULT ".$column_default; + } + if ($is_an_index) { + $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; + } + if (!$this->_mysqli->query($sql_query)) { + $this->WriteLog("Error: ".nullable_trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $result = FALSE; + } + } else { + $result = TRUE; + $sql_query = "ALTER TABLE ".$table." CHANGE `".$column."` `".$column."` ".$column_type; + if ($column_default != NULL) { + $sql_query.= " DEFAULT ".$column_default; + } + $sql_query_index = "ALTER TABLE ".$table." DROP INDEX `".$column."`;"; + try { $this->_mysqli->query($sql_query_index); } catch(Exception $e) { } + if ($is_an_index) { + $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; + } + if (!$this->_mysqli->query($sql_query)) { + $this->WriteLog("Error: ".nullable_trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $result = FALSE; + } + } + } + catch(Exception $e) { + $sql_query = "ALTER TABLE ".$table." ADD `".$column."` ".$column_type; + if ($column_default != NULL) { + $sql_query.= " DEFAULT ".$column_default; } + if ($is_an_index) { + $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; + } + if (!$this->_mysqli->query($sql_query)) { + $this->WriteLog("Error: ".nullable_trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $result = FALSE; + } + } } elseif (NULL != $this->_mysql_database_link) { - $sql_query = "SELECT `".$column."` FROM ".$table; - if (($select_row = mysql_query($sql_query, $this->_mysql_database_link))) { - $result = TRUE; - $sql_query = "ALTER TABLE ".$table." CHANGE `".$column."` `".$column."` ".$column_type; - if ($column_default != NULL) { - $sql_query.= " DEFAULT ".$column_default; - } - $sql_query_index = "ALTER TABLE ".$table." DROP INDEX `".$column."`;"; - try {mysql_query($sql_query_index, $this->_mysql_database_link); } catch(Exception $e) { } - if ($is_an_index) { - $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; - } - if (!mysql_query($sql_query, $this->_mysql_database_link)) { - $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); - $result = FALSE; - } - } elseif (!$select_row) { - $sql_query = "ALTER TABLE ".$table." ADD `".$column."` ".$column_type; - if ($column_default != NULL) { - $sql_query.= " DEFAULT ".$column_default; - } - if ($is_an_index) { - $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; - } - if (!mysql_query($sql_query, $this->_mysql_database_link)) { - $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); - $result = FALSE; - } + $sql_query = "SELECT `".$column."` FROM ".$table; + try { + $select_row = mysql_query($sql_query, $this->_mysql_database_link); + // Backward compatibility + if (!$select_row) { + $sql_query = "ALTER TABLE ".$table." ADD `".$column."` ".$column_type; + if ($column_default != NULL) { + $sql_query.= " DEFAULT ".$column_default; + } + if ($is_an_index) { + $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; + } + if (!mysql_query($sql_query, $this->_mysql_database_link)) { + $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $result = FALSE; + } + } else { + $select_row = mysql_query($sql_query, $this->_mysql_database_link); + $result = TRUE; + $sql_query = "ALTER TABLE ".$table." CHANGE `".$column."` `".$column."` ".$column_type; + if ($column_default != NULL) { + $sql_query.= " DEFAULT ".$column_default; + } + $sql_query_index = "ALTER TABLE ".$table." DROP INDEX `".$column."`;"; + try {mysql_query($sql_query_index, $this->_mysql_database_link); } catch(Exception $e) { } + if ($is_an_index) { + $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; + } + if (!mysql_query($sql_query, $this->_mysql_database_link)) { + $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $result = FALSE; + } + } + } + catch(Exception $e) { + $sql_query = "ALTER TABLE ".$table." ADD `".$column."` ".$column_type; + if ($column_default != NULL) { + $sql_query.= " DEFAULT ".$column_default; } + if ($is_an_index) { + $sql_query.= " , ADD INDEX `$column` ( `".$column."`$index_special_suffix )"; + } + if (!mysql_query($sql_query, $this->_mysql_database_link)) { + $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $result = FALSE; + } + } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Error: *The database link is down!", TRUE, FALSE, 41, 'System', '', 3); } @@ -4908,17 +4991,25 @@ function OpenMysqlDatabase() } else { $sql_port = "3306"; } - $this->_mysqli = @new mysqli($sql_server, - $this->_config_data['sql_username'], - $this->_config_data['sql_password'], - $this->_config_data['sql_database'], - $sql_port); - if (0 != $this->_mysqli->connect_errno) { - $this->WriteLog("Error: Bad SQL authentication parameters, ".$this->_mysqli->connect_errno.', '.trim($this->_mysqli->connect_error), TRUE, FALSE, 41, 'System', '', 3); - unset($this->_mysqli); - $this->_mysqli = NULL; - } else { - $result = TRUE; + + try { + $this->_mysqli = @new mysqli($sql_server, + $this->_config_data['sql_username'], + $this->_config_data['sql_password'], + $this->_config_data['sql_database'], + $sql_port); + if (0 != $this->_mysqli->connect_errno) { + $this->WriteLog("Error: Bad SQL authentication parameters, ".$this->_mysqli->connect_errno.', '.nullable_trim($this->_mysqli->connect_error), TRUE, FALSE, 41, 'System', '', 3); + unset($this->_mysqli); + $this->_mysqli = NULL; + } else { + $result = TRUE; + } + } + catch(Exception $e) { + $this->WriteLog("Error: SQL connection error", TRUE, FALSE, 41, 'System', '', 3); + unset($this->_mysqli); + $this->_mysqli = NULL; } } elseif (!($this->_mysql_database_link = mysql_connect($this->_config_data['sql_server'], $this->_config_data['sql_username'], @@ -4953,7 +5044,7 @@ function PGSQLAddRowIfNeeded( $result = TRUE; $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ALTER COLUMN \"".$column."\" TYPE ".$column_type; if (!@pg_query($this->_pgsql_database_link, $sql_query)) { - $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { if ($column_default != NULL) { @@ -4962,20 +5053,20 @@ function PGSQLAddRowIfNeeded( $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ALTER COLUMN \"".$column."\" DROP DEFAULT"; } if (!@pg_query($this->_pgsql_database_link, $sql_query)) { - $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } } elseif (!$select_row) { $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ADD COLUMN \"".$column."\" ".$column_type.($column_default != NULL ? " DEFAULT ".$column_default : ""); if (!@pg_query($this->_pgsql_database_link, $sql_query)) { - $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } if ($is_an_index) { $sql_query = "CREATE INDEX \"".$table."_".$column."_idx\" ON \"".$this->_config_data['sql_schema']."\".\"".$table."\" ( \"".$column."\" )"; if(!@pg_query($this->_pgsql_database_link, $sql_query)) { - $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } @@ -5012,10 +5103,18 @@ function OpenPGSQLDatabase() $pgsql_connect_string.= "dbname=".$this->_config_data['sql_database']." "; $pgsql_connect_string.= "user=".$this->_config_data['sql_username']." "; $pgsql_connect_string.= "password=".$this->_config_data['sql_password']; - if (!($this->_pgsql_database_link = pg_connect($pgsql_connect_string))) { - $this->WriteLog("Error: Bad SQL authentication parameters, ".pg_last_error(), TRUE, FALSE, 41, 'System', '', 3); - } else { - $result = TRUE; + try { + if (!($this->_pgsql_database_link = @pg_connect($pgsql_connect_string))) { + $this->_pgsql_database_link = NULL; + $this->WriteLog("Error: Bad SQL authentication", TRUE, FALSE, 41, 'System', '', 3); + } else { + $result = TRUE; + } + } + catch(Exception $e) + { + $this->_pgsql_database_link = NULL; + $this->WriteLog("Error: Bad SQL authentication", TRUE, FALSE, 41, 'System', '', 3); } } } @@ -5034,10 +5133,10 @@ function InitializeBackend() $sql_query = "CREATE TABLE IF NOT EXISTS `".$this->_config_data['sql_'.$sql_table.'_table']."` (unique_id bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (unique_id));"; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sql_query))) { - $this->WriteLog("Error: Bad SQL request ($sql_query), ".trim($this->_mysqli->error), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: Bad SQL request ($sql_query), ".nullable_trim($this->_mysqli->error), TRUE, FALSE, 40, 'System', '', 3); return 41; } - } elseif (!mysql_query($sql_query, $this->_mysql_database_link)) { + } elseif ((NULL != $this->_mysql_database_link) && (!mysql_query($sql_query, $this->_mysql_database_link))) { $this->WriteLog("Error: Bad SQL request (CREATE TABLE ".$this->_config_data['sql_'.$sql_table.'_table']."), ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); return 41; } @@ -5046,8 +5145,8 @@ function InitializeBackend() $row_default = NULL; $pos = mb_strpos(mb_strtoupper($row_format,'UTF-8'), 'DEFAULT'); if ($pos !== FALSE) { - $row_default = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); - $row_format = trim(mb_substr($row_format, 0, $pos)); + $row_default = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $row_format = nullable_trim(mb_substr($row_format, 0, $pos)); if (mb_strtolower(mb_substr($row_format, 0, 4),'UTF-8') == "text") { // No default in database for TEXT format $row_default = NULL; @@ -5066,7 +5165,7 @@ function InitializeBackend() if ("" != $this->_config_data['sql_'.$sql_table.'_table']) { $sql_query = "CREATE TABLE IF NOT EXISTS \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$sql_table.'_table']."\" (\"unique_id\" BIGSERIAL PRIMARY KEY);"; if (!pg_query($this->_pgsql_database_link, $sql_query)) { - $this->WriteLog("Error: Bad SQL request (CREATE TABLE ".$_config_data['sql_schema'].".".$this->_config_data['sql_'.$sql_table.'_table']."), ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); + $this->WriteLog("Error: Bad SQL request (CREATE TABLE ".$_config_data['sql_schema'].".".$this->_config_data['sql_'.$sql_table.'_table']."), ".pg_last_error($this->_pgsql_database_link), TRUE, FALSE, 40, 'System', '', 3); return 41; } foreach ($this->_sql_tables_schema[$sql_table] as $valid_key => $valid_format) { @@ -5079,8 +5178,8 @@ function InitializeBackend() } $pos = mb_strpos(mb_strtoupper($row_format,'UTF-8'), 'DEFAULT'); if ($pos !== FALSE) { - $row_default = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); - $row_format = trim(mb_substr($row_format, 0, $pos)); + $row_default = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $row_format = nullable_trim(mb_substr($row_format, 0, $pos)); } $this->PGSQLAddRowIfNeeded($this->_config_data['sql_'.$sql_table.'_table'], $valid_key, $row_format, $row_default, (FALSE !== mb_strpos($this->_sql_tables_index[$sql_table], "*".$valid_key."*"))); } @@ -5137,13 +5236,13 @@ function ReadConfigData( if (file_exists($this->GetConfigFolder(false, !$encryption_only).$config_filename)) { if ($file_handler = @fopen($this->GetConfigFolder(false, !$encryption_only).$config_filename, "rt")) { - $first_line = trim(fgets($file_handler)); + $first_line = nullable_trim(fgets($file_handler)); while (!feof($file_handler)) { $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($file_handler))); $line_array = explode("=",$line,2); - if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) + if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != nullable_trim($line)) && (isset($line_array[1]))) { if (":" == mb_substr($line_array[0], -1)) { @@ -5194,7 +5293,7 @@ function ReadConfigData( if (is_object($this->_mysqli)) { if (!($result = @$this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: ".nullable_trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = $result->fetch_assoc(); @@ -5256,7 +5355,7 @@ function ReadConfigData( $aRow = NULL; if (!($rResult = @pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: ".pg_last_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); @@ -5320,7 +5419,7 @@ function ReadConfigData( $this->EnableDisplayLog(); } - $this->SetAttributesToEncrypt(trim(isset($this->_config_data['attributes_to_encrypt'])?$this->_config_data['attributes_to_encrypt']:"")); + $this->SetAttributesToEncrypt(nullable_trim(isset($this->_config_data['attributes_to_encrypt'])?$this->_config_data['attributes_to_encrypt']:"")); $timezone = $this->GetTimezone(); // Read the timezone (and set it in PHP automatically) @@ -5339,7 +5438,7 @@ function ReadConfigData( $pos = mb_strpos(mb_strtoupper($stat_format,'UTF-8'), 'DEFAULT'); $default_value = ""; if ($pos !== FALSE) { - $default_value = trim(mb_substr($stat_format, $pos + mb_strlen("DEFAULT"))); + $default_value = nullable_trim(mb_substr($stat_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($default_value,0,1)) && ("'" == mb_substr($default_value,-1))) { $default_value = mb_substr($default_value,1,-1); } @@ -5371,12 +5470,12 @@ function ReadStatData() $stat_filename = 'stat.ini'; // File exists in v3 format only, we don't need any conversion if (file_exists($this->GetConfigFolder().$stat_filename)) { if ($file_handler = @fopen($this->GetConfigFolder().$stat_filename, "rt")) { - $first_line = trim(fgets($file_handler)); + $first_line = nullable_trim(fgets($file_handler)); while (!feof($file_handler)) { $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($file_handler))); $line_array = explode("=",$line,2); - if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) { + if (('#' != mb_substr($line, 0, 1)) && (';' != mb_substr($line, 0, 1)) && ("" != nullable_trim($line)) && (isset($line_array[1]))) { if ("" != $line_array[0]) { $this->_stat_data[mb_strtolower($line_array[0],'UTF-8')] = $line_array[1]; } @@ -5400,7 +5499,7 @@ function ReadStatData() if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { - $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: ".nullable_trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = $result->fetch_assoc(); @@ -5445,7 +5544,7 @@ function ReadStatData() $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { - $this->WriteLog("Error: ".pg_last_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); + $this->WriteLog("Error: ".pg_last_error($this->_pgsql_database_link)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); @@ -5622,7 +5721,7 @@ function ResetTempUserArray() $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -5656,7 +5755,7 @@ function ResetTokenArray() $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -5677,7 +5776,7 @@ function ResetDdnsArray() $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -5694,7 +5793,7 @@ function ResetDeviceArray() $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -5711,7 +5810,7 @@ function ResetGroupArray() $pos = mb_strpos(mb_strtoupper($valid_format,'UTF-8'), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { - $value = trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); + $value = nullable_trim(mb_substr($valid_format, $pos + mb_strlen("DEFAULT"))); if (("'" == mb_substr($value,0,1)) && ("'" == mb_substr($value,-1))) { $value = mb_substr($value,1,-1); } @@ -5724,7 +5823,7 @@ function ResetGroupArray() function CleanPhoneNumber( $phone_number ) { - $pn = trim(preg_replace('[\D]', "", $phone_number)); + $pn = nullable_trim(preg_replace('[\D]', "", $phone_number)); // $pn_len = mb_strlen($pn); if ('00' == mb_substr($pn,0, 2)) { @@ -5827,13 +5926,13 @@ function GetWebsite() function SetSourceTag( $value = "" ) { - $this->_source_tag = trim($value); + $this->_source_tag = nullable_trim($value); } function GetSourceTag() { - return trim($this->_source_tag); + return nullable_trim($this->_source_tag); } @@ -6013,7 +6112,7 @@ function SetNtKey( ) { $temp = $hex_value; if (16 == strlen($temp)) { - $temp = bin2hex($temp); + $temp = nullable_bin2hex($temp); } $pos = strpos(strtolower($temp), 'x'); if (FALSE !== $pos) { @@ -6030,7 +6129,7 @@ function GetNtKey() { $temp = $this->_ms_nt_key; if (16 == strlen($temp)) { - $temp = bin2hex($temp); + $temp = nullable_bin2hex($temp); } elseif (32 != strlen($temp)) { $temp = ''; } @@ -6044,7 +6143,7 @@ function SetState( if ((0 === mb_strpos($value, '0x')) && (0 == (mb_strlen($value) % 2))) { $value = hex2bin(mb_substr($value, 2)); } - $this->_state = trim($value); + $this->_state = nullable_trim($value); } @@ -6054,7 +6153,7 @@ function GetState() if ((0 === mb_strpos($value, '0x')) && (0 == (mb_strlen($value) % 2))) { $value = hex2bin(mb_substr($value, 2)); } - return trim($value); + return nullable_trim($value); } @@ -6519,8 +6618,8 @@ function IsLdapSsl() function SetLdapLanguageAttribute( $value ) { - if ('' != trim($value)) { - $this->_config_data['ldap_language_attribute'] = trim($value); + if ('' != nullable_trim($value)) { + $this->_config_data['ldap_language_attribute'] = nullable_trim($value); } } @@ -6547,8 +6646,8 @@ function GetLdapAccountSuffix() function SetLdapCnIdentifier( $value ) { - if ('' != trim($value)) { - $this->_config_data['ldap_cn_identifier'] = trim($value); + if ('' != nullable_trim($value)) { + $this->_config_data['ldap_cn_identifier'] = nullable_trim($value); } } @@ -6556,7 +6655,7 @@ function SetLdapCnIdentifier( function GetLdapCnIdentifier() { $value = $this->_config_data['ldap_cn_identifier']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "sAMAccountName"; } return ($value); @@ -6566,14 +6665,14 @@ function GetLdapCnIdentifier() function SetLdapSyncedUserAttribute( $value ) { - $this->_config_data['ldap_synced_user_attribute'] = trim($value); + $this->_config_data['ldap_synced_user_attribute'] = nullable_trim($value); } function GetLdapSyncedUserAttribute() { $result = ($this->_config_data['ldap_synced_user_attribute']); - if ("" == trim($result)) { + if ("" == nullable_trim($result)) { $result = $this->GetLdapCnIdentifier(); } return $result; @@ -6598,8 +6697,8 @@ function GetLdapDefaultAlgorithm() function SetLdapGroupCnIdentifier( $value ) { - if ('' != trim($value)) { - $this->_config_data['ldap_group_cn_identifier'] = trim($value); + if ('' != nullable_trim($value)) { + $this->_config_data['ldap_group_cn_identifier'] = nullable_trim($value); } } @@ -6607,7 +6706,7 @@ function SetLdapGroupCnIdentifier( function GetLdapGroupCnIdentifier() { $value = $this->_config_data['ldap_group_cn_identifier']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "cn"; } return ($value); @@ -6684,7 +6783,7 @@ function SetLdapBaseDn( function GetLdapBaseDn( $return_alternate_if_needed = FALSE ) { - if ($return_alternate_if_needed && ('' == trim($this->_config_data['ldap_base_dn']))) { + if ($return_alternate_if_needed && ('' == nullable_trim($this->_config_data['ldap_base_dn']))) { return $this->_config_data['ldap_users_dn']; } else { return $this->_config_data['ldap_base_dn']; @@ -6702,7 +6801,7 @@ function SetLdapUsersDn( function GetLdapUsersDn( $return_alternate_if_needed = FALSE ) { - if ($return_alternate_if_needed && ('' == trim($this->_config_data['ldap_users_dn']))) { + if ($return_alternate_if_needed && ('' == nullable_trim($this->_config_data['ldap_users_dn']))) { return $this->_config_data['ldap_base_dn']; } else { return $this->_config_data['ldap_users_dn']; @@ -6726,7 +6825,7 @@ function GetLdapBindDn() function SetLdapDomainControllers( $value ) { - $this->_config_data['ldap_domain_controllers'] = trim($value); + $this->_config_data['ldap_domain_controllers'] = nullable_trim($value); } @@ -6740,7 +6839,7 @@ function GetLdapPrimaryController() { $domain_controllers = str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())); $controllers_array = explode(" ",$this->GetLdapDomainControllers()); - return trim(isset($controllers_array[0])?$controllers_array[0]:''); + return nullable_trim(isset($controllers_array[0])?$controllers_array[0]:''); } @@ -6748,16 +6847,16 @@ function GetLdapSecondaryController() { $domain_controllers = str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())); $controllers_array = explode(" ",$this->GetLdapDomainControllers()); - return trim(isset($controllers_array[1])?$controllers_array[1]:''); + return nullable_trim(isset($controllers_array[1])?$controllers_array[1]:''); } function SetLdapInGroup( $value ) { - $this->_config_data['ldap_in_group'] = trim($value); + $this->_config_data['ldap_in_group'] = nullable_trim($value); - $ldap_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + $ldap_in_group_array = explode("\t",nullable_trim(str_replace(",","\t",str_replace(";","\t",$value)))); $groups_array = array(); $list = explode("\t", $this->GetGroupsList()); @@ -6770,9 +6869,9 @@ function SetLdapInGroup( } foreach ($ldap_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)); + if (!in_array(nullable_trim($one_group), $groups_array)) { + if ('' != nullable_trim($one_group)) { + $this->CreateGroup('', nullable_trim($one_group), nullable_trim($one_group)); } } } @@ -6781,7 +6880,7 @@ function SetLdapInGroup( function GetLdapInGroup($included_without2fa = false) { - $groups = trim($this->_config_data['ldap_in_group']); + $groups = nullable_trim($this->_config_data['ldap_in_group']); if ((true === $included_without2fa) && ('' != $groups) && ('' != $this->GetLdapWithout2faInGroup())) { $groups = $this->GetLdapWithout2faInGroup() . "," . $groups; } @@ -6792,9 +6891,9 @@ function GetLdapInGroup($included_without2fa = false) function SetLdapWithout2faInGroup( $value ) { - $this->_config_data['ldap_without2fa_in_group'] = trim($value); + $this->_config_data['ldap_without2fa_in_group'] = nullable_trim($value); - $ldap_without2fa_in_group_array = explode("\t",trim(str_replace(",","\t",str_replace(";","\t",$value)))); + $ldap_without2fa_in_group_array = explode("\t",nullable_trim(str_replace(",","\t",str_replace(";","\t",$value)))); $groups_array = array(); $list = explode("\t", $this->GetGroupsList()); @@ -6807,9 +6906,9 @@ function SetLdapWithout2faInGroup( } 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)); + if (!in_array(nullable_trim($one_group), $groups_array)) { + if ('' != nullable_trim($one_group)) { + $this->CreateGroup('', nullable_trim($one_group), nullable_trim($one_group)); } } } @@ -6825,8 +6924,8 @@ function GetLdapWithout2faInGroup() function SetLdapGroupAttribute( $value ) { - if ('' != trim($value)) { - $this->_config_data['ldap_group_attribute'] = trim($value); + if ('' != nullable_trim($value)) { + $this->_config_data['ldap_group_attribute'] = nullable_trim($value); } } @@ -6834,7 +6933,7 @@ function SetLdapGroupAttribute( function GetLdapGroupAttribute() { $value = $this->_config_data['ldap_group_attribute']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "memberOf"; } return ($value); @@ -6915,6 +7014,19 @@ function GetLdapServerType() } + function SetLdapFilter( + $value = '' + ) { + $this->_config_data['ldap_filter'] = trim($value); + } + + + function GetLdapFilter() + { + return $this->_config_data['ldap_filter']; + } + + function SetLdapTimeLimit( $value ) { @@ -6970,14 +7082,14 @@ function GetLdapHashCacheTime() function SetLdapTlsReqcert( $value ) { - $this->_config_data['ldaptls_reqcert'] = trim($value); + $this->_config_data['ldaptls_reqcert'] = nullable_trim($value); } function GetLdapTlsReqcert() { $value = $this->_config_data['ldaptls_reqcert']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "auto"; } return ($value); @@ -6987,14 +7099,14 @@ function GetLdapTlsReqcert() function SetLdapTlsCipherSuite( $value ) { - $this->_config_data['ldaptls_cipher_suite'] = trim($value); + $this->_config_data['ldaptls_cipher_suite'] = nullable_trim($value); } function GetLdapTlsCipherSuite() { $value = $this->_config_data['ldaptls_cipher_suite']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "auto"; } return ($value); @@ -7036,7 +7148,7 @@ function SetSmsMessage( function GetSmsMessage() { $value = $this->_config_data['sms_message_prefix']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "%s is your SMS-Code"; } return ($value); @@ -7228,7 +7340,7 @@ function SetServerSecret( function GetServerSecret($specific_ip = "") { $value = $this->_config_data['server_secret']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "ClientServerSecret"; } return ($value); @@ -7245,7 +7357,7 @@ function SetServerType( function GetServerType() { $value = $this->_config_data['server_type']; - if ("" == trim($value)) { + if ("" == nullable_trim($value)) { $value = "xml"; } return ($value); @@ -7268,14 +7380,14 @@ function GetServerTimeout() function SetServerUrl( $value ) { - $cleaned_server_url = trim(str_replace(",",";",str_replace(" ",";",$value))); + $cleaned_server_url = nullable_trim(str_replace(",",";",str_replace(" ",";",$value))); $this->_config_data['server_url'] = $cleaned_server_url; } function GetServerUrl() { - $cleaned_server_url = trim(str_replace(",",";",str_replace(" ",";",$this->_config_data['server_url']))); + $cleaned_server_url = nullable_trim(str_replace(",",";",str_replace(" ",";",$this->_config_data['server_url']))); $this->_config_data['server_url'] = $cleaned_server_url; return $cleaned_server_url; } @@ -7397,13 +7509,13 @@ function IsGlobalSmsChallenge() { function SetGlobalTextSmsChallenge($value) { - $this->_config_data['text_sms_challenge'] = trim($value); + $this->_config_data['text_sms_challenge'] = nullable_trim($value); } function GetGlobalTextSmsChallenge() { - $value = trim($this->_config_data['text_sms_challenge']); - if ("" == trim($value)) { + $value = nullable_trim($this->_config_data['text_sms_challenge']); + if ("" == nullable_trim($value)) { $value = "Please enter the code received on your mobile phone"; } return ($value); @@ -7411,13 +7523,13 @@ function GetGlobalTextSmsChallenge() { function SetGlobalTextTokenChallenge($value) { - $this->_config_data['text_token_challenge'] = trim($value); + $this->_config_data['text_token_challenge'] = nullable_trim($value); } function GetGlobalTextTokenChallenge() { - $value = trim($this->_config_data['text_token_challenge']); - if ("" == trim($value)) { + $value = nullable_trim($this->_config_data['text_token_challenge']); + if ("" == nullable_trim($value)) { $value = "Please enter the code displayed on the token"; } return ($value); @@ -7475,9 +7587,9 @@ function IsEncodeFileId() function EncodeFileId($id, $case_sensitive = FALSE, $force_regular = FALSE) { if ($this->IsEncodeFileId() && (!$force_regular)) { if ($case_sensitive) { - return "id0x".bin2hex($id); + return "id0x".nullable_bin2hex($id); } else { - return "id0x".bin2hex(mb_strtolower($id,'UTF-8')); + return "id0x".nullable_bin2hex(mb_strtolower($id,'UTF-8')); } } else { if ($case_sensitive) { @@ -7507,7 +7619,7 @@ function SetNtpServer( function GetNtpServer() { - return trim($this->_config_data['ntp_server']); + return nullable_trim($this->_config_data['ntp_server']); } @@ -7547,7 +7659,7 @@ function SetRadiusReplySeparator( $radius_reply_separator = ';'; break; } - $this->_config_data['radius_reply_separator_hex'] = bin2hex($radius_reply_separator); + $this->_config_data['radius_reply_separator_hex'] = nullable_bin2hex($radius_reply_separator); } @@ -7588,7 +7700,7 @@ function SetTimezone( function GetTimezone() { - $timezone = trim(isset($this->_config_data['timezone'])?$this->_config_data['timezone']:''); + $timezone = nullable_trim(isset($this->_config_data['timezone'])?$this->_config_data['timezone']:''); if (('' != $timezone) && (function_exists('date_default_timezone_set'))) { date_default_timezone_set($timezone); @@ -8135,7 +8247,7 @@ function CalculateMsChapResponse( $hash_for_nt_key = $this->NtPasswordHash($secret); } - $this->SetNtKey(bin2hex($this->NtPasswordHashHash($hash))); + $this->SetNtKey(nullable_bin2hex($this->NtPasswordHashHash($hash))); $challenge = $mschap_challenge; @@ -8155,11 +8267,11 @@ function CalculateMsChapResponse( if ($calculated_response == $response) { - $result = strtolower(bin2hex($mschap_response)); + $result = strtolower(nullable_bin2hex($mschap_response)); } else { - $result = 'Error: '.bin2hex($calculated_response).' instead of '.bin2hex($nt_response); + $result = 'Error: '.nullable_bin2hex($calculated_response).' instead of '.nullable_bin2hex($nt_response); } return $result; } @@ -8214,7 +8326,7 @@ function CalculateMsChap2Response( $hash = $this->NtPasswordHash($secret); - $this->SetNtKey(bin2hex($this->NtPasswordHashHash($hash))); + $this->SetNtKey(nullable_bin2hex($this->NtPasswordHashHash($hash))); /* $kr = hash_hmac('md5', @@ -8260,11 +8372,11 @@ function CalculateMsChap2Response( if ($calculated_response == $nt_response) { - $result = strtolower(bin2hex($mschap2_response)); + $result = strtolower(nullable_bin2hex($mschap2_response)); } else { - $result = 'Error: '.bin2hex($calculated_response).' instead of '.bin2hex($nt_response); + $result = 'Error: '.nullable_bin2hex($calculated_response).' instead of '.nullable_bin2hex($nt_response); } return $result; } @@ -8466,7 +8578,7 @@ function CreateUser($user_raw, // A user cannot be created with one (or more) leading backslash $user = str_replace("\\", "", $user_raw); $result = FALSE; - if ('' != trim($user)) { + if ('' != nullable_trim($user)) { if ((intval($ldap_pwd_needed) < 0) && (1 == $synchronized)) { $request_ldap_pwd = $this->GetDefaultRequestLdapPwd(); } else { @@ -8523,13 +8635,13 @@ function CreateUser($user_raw, $this->SetUserTokenLastEvent($next_event - 1); $this->SetUserTokenTimeInterval($time_interval); - $this_email = trim($email); + $this_email = nullable_trim($email); if (('' == $this_email) && (FALSE !== mb_strpos($user, '@'))) { $this_email = $user; } $this->SetUserEmail($this_email); - $this->SetUserGroup(trim($group)); + $this->SetUserGroup(nullable_trim($group)); $this->SetUserSms($sms); $this->SetUserDescription($description); $this->SetUserActivated($activated); @@ -8628,7 +8740,7 @@ function CreateUserFromToken($user_raw, $the_pin = mt_rand(1000,9999); } - $this_email = trim($email); + $this_email = nullable_trim($email); if (('' == $this_email) && (FALSE !== mb_strpos($user, '@'))) { $this_email = $user; @@ -8636,7 +8748,7 @@ function CreateUserFromToken($user_raw, $this->SetUserPin($the_pin); $this->SetUserEmail($this_email); - $this->SetUserGroup(trim($group)); + $this->SetUserGroup(nullable_trim($group)); $this->SetUserSms($sms); $this->SetUserDescription($description); @@ -8737,7 +8849,7 @@ function GenerateHtmlQrCode( $descr = encode_utf8_if_needed(empty($descr) ? $user : $descr); $display_name = encode_utf8_if_needed($this->GetUserDisplayName()); - if ('' != trim($alternate_html_template)) { + if ('' != nullable_trim($alternate_html_template)) { $html = $alternate_html_template; } else { //Get template file @@ -8779,7 +8891,7 @@ function GenerateHtmlQrCode( $html = preg_replace('//i', '/i', ' -- {/IfMultiotpUserTokenSerial} -->', $html); $html = preg_replace('//i', '/i', '/i', ' -- {/IfMultiotpUserTokenSerial} -->', $html); $html = preg_replace('//i', '/i', '/i', ' -- {/IfMultiotpUserTokenSerial} -->', $html); $html = preg_replace('//i', '/i', '/i', ' -- {/IfMultiotpUserTokenSerial} -->', $html); $html = preg_replace('//i', '/i', '/i', ' -- {/IfMultiotpUserTokenSerial} -->', $html); $html = preg_replace('//i', '