Compare commits

...

161 Commits

Author SHA1 Message Date
d4b19d07db Updated version to 1.2.6.6 2023-04-02 00:46:16 +11:00
85f8c61e80 Fix for Setting of IV length for AEAD mode failed - closes #183 2023-04-02 00:36:15 +11:00
1650d6a921 Another fix for CVE-2020-35132 - closes #137, missed from #130 2023-04-02 00:25:47 +11:00
Deon George
c84b2d6d91 Updated version to 1.2.6.5 2023-02-15 17:36:15 +11:00
Deon George
ef8d0ce94c Fix mistake in patch #176 as identified in #170 2023-02-15 17:33:47 +11:00
Eric Lavault
15cc6f5382 Issue #165 Proper check for memory_limit config (#180)
* fix #165 : Handle shorthand notation for PHP memory_limit check

* fix config default memory threshold.
2023-02-15 17:24:19 +11:00
bendem
364c0565a2 don't apply preventXSS on 'filter' parameters in export and search (#168)
fixes #98
2023-01-20 20:08:49 +11:00
jmptbl
d09aa72a42 Inactivity message format fix (#171) 2023-01-20 20:08:07 +11:00
Klaus Tachtler
7226cea874 #170 - issue - openssl 3.0 patch (#176)
* Updated README with info on PLA v2

* Fix broken git command in readme - closes #124

* #170 - issue - openssl 3.0 patch

Co-authored-by: Deon George <deon@leenooks.net>
2023-01-20 20:06:44 +11:00
bendem
d15bd2dab3 Don't do any decoding on the password field (#163)
Fixes #162
2022-08-18 10:44:43 +10:00
Benjamin Renard
43bac58990 Add support of argon2i & argon2id password hash types
Closes pull-request #158
2022-08-05 10:49:10 +10:00
Patrick Monnerat
9488fe2ed7 Avoid passing a null value to PHP functions where another type is expected.
PHP 8.1 deprecates this feature.

Closes pull-request #149 and closes #150
2022-08-05 10:48:56 +10:00
Patrick Monnerat
5e9b95f9a8 Avoid 32-bit signed integer overflow in Blowfish computations.
PHP 8.1 deprecates float to int truncation.
2022-08-05 10:48:56 +10:00
Patrick Monnerat
aeebf3faa6 Replace calls to strftime() by calls to date().
PHP 8.1 deprecates strftime().
2022-08-05 10:48:56 +10:00
Patrick Monnerat
b035e8a0f4 Do not use function is_resource().
PHP 8.1 replaces some kind of resources by built-in class instances.
As is_resource() is always used to test for failures, replace calls by
simple Boolean checks.
2022-08-05 10:48:56 +10:00
Patrick Monnerat
f129579f45 Adapt app_error_handler() to PHP 8.
In an '@ error suppression context, PHP 8 error_reporting() no longer
returns 0 but an error mask of errors that cannot be supressed and
passes the effective error number to the error handler (instead of 0).

Adapt the test in a compatible way.
2022-08-05 10:48:56 +10:00
Patrick Monnerat
c90dc06af2 Rename class Attribute to PLAAttribute.
As PHP 8 introduces a built-in Attribute class, a name clash occurs
without this commit.

Class names are used by the Visitor class to dynamically build method
names. To avoid having to also rename the target methods, a class name
mapping is introduced for this purpose. This map may be augmented
whenever another similar case occurs.
2022-08-05 10:48:56 +10:00
Patrick Monnerat
3a75a32100 Mandatory function arguments must be listed before optional ones.
PHP 8 deprecates the ability to have
	function whatever($arg1, $arg2='something', $arg3)

This commit reorders arguments of functions set_cached_item() and
draw_jpeg_photo() to meet this new requirement.
2022-08-05 10:48:56 +10:00
Patrick Monnerat
3ec9c23d58 Do not call get_magic_quote_gpc() when running in PHP version >= 5.4.
This deprecated function has been removed in PHP 8.
2022-08-05 10:48:56 +10:00
KuhnChris
857f0c539c sanity-fix: gettext and session mod check
Closes pull-request #152
2022-08-05 10:48:56 +10:00
Andrés Maldonado
97eed9d9cd Prevent strftime overflow on 32 bit systems
Fixes "strftime() expects parameter 2 to be integer, float given"

Closes pull request #156 and closes #155
2022-08-05 10:48:31 +10:00
Deon George
d4cae5065b Updated version to 1.2.6.3 2021-12-12 13:35:51 +11:00
Deon George
386d6ab83b Fix syntax error created by a0de69b - thanks to Bert Van de Poel for testing this and identifying the error 2021-12-12 13:25:28 +11:00
Deon George
1d26d435c2 Special character issue in password - closes #104 2021-12-10 16:14:04 +11:00
Deon George
a0de69bd58 foreach error in lib_ldap_pla.php:checkUniqueAttrs when uidpool is turned on - closes #20 2021-12-10 16:05:01 +11:00
EtienneBarbier
a8c9abe22b Add option to list available password types - closes #143 2021-12-10 15:56:58 +11:00
Bert Van de Poel
1c7340ce48 Correct incorrent mixing of tabs and spaces.
All code (including code originating from the blowfish PR) now correctly use tabs. Spaces are only used for alignment in comments where necessary.
2021-12-10 15:18:26 +11:00
Bert Van de Poel
24ce5d5833 Replace salt function with a more modern, cryptographically secure pseudo-random method
Set minimum PHP version to 7.0.0 for random_bytes
2021-12-10 15:18:18 +11:00
Bert Van de Poel
fe3798f8ec Modernize sha1 and md5 password hash and check functions: remove unnecessary pack, no longer use very old fallbacks, and use random_salt 2021-12-10 15:18:09 +11:00
Bert Van de Poel
1a09e4ff3c Modernize sha512 hash code: replace openssl_digest with the generic hash function, remove check no longer necessary in minimum version 2021-12-10 15:18:01 +11:00
Bert Van de Poel
bc1691f5d2 Add hash support for ssha512 2021-12-10 15:17:54 +11:00
Bert Van de Poel
54bb4743aa Add hash support for salted and non-salted sha256 and sha384 (therefore adding full support for all hashes in the sha2 openLDAP module) 2021-12-10 15:17:43 +11:00
Franky Van Liedekerke
46cc4a1b13 Take into account empty arguments
If no argument is given to the function call, don't try to pass an empty array as some php functions don't allow arguments (like the time function)
2021-12-10 15:09:18 +11:00
Maarten
45aa1e5208 Added script comment for the Autofill A flag 2021-12-10 15:06:36 +11:00
Maarten
02b047c1f5 Bug fix: typo in regex 2021-12-10 15:06:36 +11:00
Maarten
6d4aff8733 Added optional delimiter to /K autofill function 2021-12-10 15:06:36 +11:00
Scott Shambarger
00683b3ea7 Added TLS client certificate support
Adds configuration for TLS client certificates to secure TLS connection
(requires PHP 7.1+ to use).
Updates use of ldap_set_option to report errors if settings fail.
Modifies connection logic to fail if connection preparation fails
(eg. to avoid connections over insecure links if requested TLS fails).
2021-12-10 15:02:31 +11:00
Scott Shambarger
da69ebf06a Added SASL EXTERNAL authentication support
New auth_type 'sasl_external'.  Login is hard coded as 'external'
2021-12-10 14:59:02 +11:00
Deon George
a8fe6f3274 Revert part of 0b657471 to fix #105 - Problem with member select list to goun 2020-09-23 10:13:11 +10:00
Deon George
0c334f0385 Fix for issue #103 - hexdec() causes an deprecation notice when invalid chars are used 2020-09-19 17:09:29 +10:00
Deon George
9fac4b415a Release 1.2.6 2020-09-19 13:45:09 +10:00
Nic Bernstein
f4c8c3d31e SF Bug #1008 getContainerPath doesn't properly traverse to baseDN and back & #1009 - return_ldap_hash should not return container object in result set 2020-08-31 08:49:02 +10:00
Andy Beefeater
e45e71fd08 SF Feature #356 - HTMLTree icons formatting 2020-08-31 08:48:49 +10:00
Deon George
0011184a3f Documenting OID 1.3.6.1.1.22 - Thank you. Closes #102 2020-08-30 22:27:03 +10:00
Deon George
aa5be41b06 Add autocomplete=off - closes #122 2020-08-30 22:09:52 +10:00
Gurvinder Dadyala
bdfd68c3b6 Added Bcrypt support (#116)
* Set minimum PHP version to 5.5.0| Bcrypt Support
* Added Bcrypt hash support
* Update Install.md
2020-08-30 21:58:50 +10:00
Armin Leuprecht
fb437b037e Decode plainpassword before check (#115)
When the user's password contains HTML special chars
the password check would always fail if the
the given plainpassword is not decoded first.
2020-08-30 21:57:40 +10:00
Bennet Bleßmann
34d4f20222 Fixes usage of deprecated array/string access syntax. (#97)
PHP 7.4 Compatibility.
2020-08-30 21:56:25 +10:00
JamesCordell
0b65747110 Changes required so the sudoRole objectClass will present a link so members can be modified by default. (#101) 2020-02-20 09:17:37 +11:00
Jakub Filak
4661aa2114 Hooks fixes (#99)
* repace deprecated each with foreach

I tried to enable the example.php hooks and the use of the keyword each
was causing crashes in the docker image osixia/phpldapadmin:0.9.0

* check if DEBUG_ENABLED is defined

I enabled the hooks example.php and I started getting crashes caused by
undefined constant.

Tested with the docker image osixia/phpldapadmin:0.9.0
2020-02-20 09:17:01 +11:00
sshambar
0a57b2f80e Added appearance option show_authz (#94)
Enabling displays the authorization ID rather than the authentication ID,
similar to using ldapwhoami.  Requires PHP 7.2+
2020-02-20 09:14:18 +11:00
sshambar
0fe1758572 Add SASL PLAIN authentication support (#92)
Adds a new sasl mech 'plain' which converts all simple authentication
methods to SASL PLAIN.  NOTE: doesn't use auth_type 'sasl' as
credentials may come from login form, stored in cookies etc...
2020-02-20 09:12:39 +11:00
Noone404
4eb3737d31 Added option to use template string for bind DN (#90)
* Language update from launchpad

* Added login option 'bind_dn_template'
2020-02-20 09:11:17 +11:00
Genaro Contreras Gutierrez
cbdc0dacd6 Auth Form wiht Google reCAPTCHA (#87)
* reCaptcha config

* config reCaptcha

* check reCAPTCHA

* add reCAPTCHA to form login

* config attributes for reCAPTCHA

* Function to verify request with reCAPTCHA

* doc reCaptcha
2020-02-20 09:04:20 +11:00
Deon George
8f4ced96f9 Release 1.2.5 2019-08-20 22:24:40 +10:00
Deon George
722fefad1c Merge pull request #84 from nayo/patch-2
Fix error and set by default to preventXSS. Closes #84 and #85
2019-08-07 16:34:53 +10:00
Genaro Contreras Gutierrez
c87571f6b7 Fix error and set by default to preventXSS 2019-07-31 08:21:14 -07:00
Deon George
cb9c0cce3e Merge pull request #82 from nayo/patch-1
Function to prevent XSS attacks
2019-07-31 07:38:06 +08:00
Genaro Contreras Gutierrez
0b10c30c79 other usage of function preventXSS
Other example of usage:
preventXSS(get_request('cmd','REQUEST'))

Additionally, the $ preventXSS parameter of the get_request function can set the default to true and in the specific fields set the parameter to false
2019-07-30 08:49:41 -07:00
Genaro Contreras Gutierrez
c22c98c463 update get_request when an error occurs
Example to use to prevent XSS attack from get_request

get_request('cmd','REQUEST',false,null,true)
2019-07-30 08:44:10 -07:00
Genaro Contreras Gutierrez
25cbb26e1d update function get_request to preventXSS
The XSS prevent function was created and used
2019-07-30 08:38:14 -07:00
Genaro Contreras Gutierrez
08c21fe7ca Prevent XSS attack since function get_request
The $preventXSS parameter was added to the get_request function to avoid XSS attacks.
It was not set by default as $preventXSS=true, because it can affect fields such as passwords.

Using "htmlspecialchars" and "addslashes" functions of PHP.
2019-07-30 08:29:17 -07:00
Deon George
1bd14ddf68 Removed reference to missing function - closes #65 2019-07-15 14:49:52 +10:00
Deon George
95411c05e1 Release 1.2.4 2019-05-14 15:01:32 +10:00
Deon George
7b1f6b5132 Fix for PHP 7.3 - deprecated continue in switch 2019-05-14 15:00:28 +10:00
Deon George
3c0ca27477 Remove SF branding 2019-04-21 23:37:10 +10:00
Deon George
511ead3ec6 Revert #63 - Add attribute not rendering correctly 2019-04-20 15:39:48 +10:00
Deon George
e37b498de1 PHP 7.2 compatibility fixes - closes #64 2019-04-19 22:48:22 +10:00
Deon George
29d7d4b2f7 Fixes #31 - Glue entries are not browsable through phpldapadmin 2019-04-19 21:01:02 +10:00
Deon George
c494078550 Closes pull request #22 and fixes #18 - preg_replace_callback changes 2019-04-19 20:08:53 +10:00
Deon George
73b7795bc0 Fixes #21 - Undefined variable: _SESSION 2019-04-18 23:17:24 +10:00
Deon George
c1af05f403 Merge pull request #63 from dago/renderfix
Fixes for translation of "Add new attribute"
2019-04-18 12:34:00 +10:00
Deon George
49ef60f26b Merge pull request #62 from spagu/patch-1
Fix php7.2 errors for function __autoload and create_function as they were deprecated.
2019-04-18 12:31:49 +10:00
Deon George
aa11e318ec Merge pull request #60 from NHellFire/php7.1
Use OpenSSL for blowfish when available (fixes #58)
2019-04-18 12:16:08 +10:00
Deon George
f3aad72b57 Merge pull request #66 from MichaelIT/master
Incompatable with openLDAP >=2.1.2
2019-04-18 11:58:12 +10:00
Deon George
6a55d808a2 Merge pull request #69 from RoyChaudhuri/master
Fix for bug #68, long redirect response
2019-04-18 11:56:25 +10:00
Deon George
aec5053f55 Merge pull request #71 from anarcat/CVE-2017-11107
Fix multiple XSS in file htdocs/entry_chooser.php (CVE-2017-11107)
2019-04-18 11:54:45 +10:00
Antoine Beaupré
4484129a41 Fix multiple XSS in file htdocs/entry_chooser.php (CVE-2017-11107)
Closes: #50

From: Ismail Belkacim <xd4rker@gmail.com>
2018-10-31 14:04:44 -04:00
Roy Chaudhuri
2e43cf95b9 Fix for bug #68, exit after redirect response when URI parameter is received by index.php 2018-09-17 15:45:42 +01:00
Michael
7569423f11 Update functions.php
Since openLDAP >=2.1.2,ldap_explode_dn turns unprintable chars (in the ASCII sense, UTF8 encoded) into \<hexcode>.
2018-07-17 19:59:11 +08:00
Dagobert Michelsen
5c0f787fbf Add URL for translation 2018-04-20 13:10:20 +02:00
Dagobert Michelsen
6c85d61525 Fix invocation of layout in TemplateRenderer 2018-04-20 12:33:58 +02:00
spagu
884cce1475 Update functions.php 2018-04-19 11:10:12 +01:00
NHellFire
53e005c1f4 Use OpenSSL for blowfish when available (fixes #58) 2018-02-11 07:22:36 +00:00
Deon George
733a10a1c5 Merge pull request #40 from PatrickBaus/master
Fixed detection of SSL encryption behind proxy server
2016-10-30 16:53:36 +08:00
Deon George
708bc5ed83 Merge pull request #37 from mr-GreyWolf/patch-1
Update functions.php
2016-10-30 16:53:05 +08:00
Deon George
e46579b34e Merge pull request #34 from gulikoza/master
Fix moving ldap entries and login error with 'fallback_dn'
2016-10-30 16:52:22 +08:00
Deon George
4fefe2aa8c Merge pull request #42 from ptomulik/crypt-sha
add support for SHA-256 and SHA-512 via crypt(3)
2016-10-30 16:47:44 +08:00
Paweł Tomulik
ee9034f24c add support for SHA-256 and SHA-512 via crypt(3) 2016-10-08 21:24:33 +02:00
Patrick Baus
61af45e872 Enabled HTTP_X_FORWARDED_PROTO header detection. It was disabled for testing. 2016-08-11 02:45:18 +02:00
Patrick Baus
dd6e9583a2 Fixed request smuggling vulnerability. See: https://www.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_HTTP_Request/Response_Smuggling
According to https://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method, the header should be ignored anyway if those properties were set.
2016-08-11 01:48:12 +02:00
Patrick Baus
665dbc2690 Fixed detection of SSL encryption, when a reverse proxy is used, that does the encryption.
If the server sets the HTTP_X_FORWARDED_PROTO header to 'https' or the
HTTP_X_FORWARDED_SSL header to 'on' SSL encryption is assumed
2016-08-11 01:32:41 +02:00
mr-GreyWolf
599d55700d Update functions.php 2016-03-30 23:07:02 +04:00
gulikoza
726190e5b8 Fix moving entries when confirm['copy'] is set.
If 'Delete after copy (move)' is selected and confirm['copy'] is set (which is default),
the entry will be copyied (created) not moved. This patch will skip confirm when entry
is being moved as there is no reason to confirm the move again.
2016-01-24 12:02:42 +01:00
gulikoza
0b8375fd2a Add additional check that full dn has been entered on login.
Fixes 'invalid dn syntax (34) for user' error when fallback_dn set and username was not found while trying to use it as dn.
2016-01-24 11:52:21 +01:00
Deon George
fa88250f0e Merge pull request #32 from jsdevel/fixing-sflogo-protocol-for-reverse-proxies
Changing the sourceforge logo to be protocol relative.
2015-12-07 16:56:41 +11:00
jsdevel
0491916d90 Changing the sourceforge logo to be protocol relative.
* This allows the browser to resolve the URL against the protocol the user used, not what a reverse proxy used.
2015-12-05 23:02:11 -07:00
Deon George
c004a291d7 Merge pull request #19 from scollin/master
Fix some monitor information problems
2015-02-23 12:40:32 -08:00
Sébastien Collin
54191d7ffb Fix some monitor information problems
Fix some monitor information problems as reported by @brendankearney
2015-01-30 13:56:29 +01:00
Deon George
9e283f369f Merge pull request #13 from DevoKun/master
Changed password_hash to pla_password_hash in a few places where it was still password_hash.
2014-10-08 12:30:58 +11:00
Devon Hubner
19114385fc Changed password_hash to pla_password_hash in a few places where it was still password_hash. 2014-10-07 14:25:32 -04:00
Deon George
7701e98bcc Merge pull request #11 from robgloess/patch-1
Fixed parse error in TemplateRender.php
2014-10-07 12:54:51 +11:00
robgloess
d4c2fb52ab Update TemplateRender.php
Fixed typo on 1682 - parse issue, non escaped " ' " causing error to be thrown
2014-09-30 22:28:09 +01:00
Deon George
7cbdd0c8db Merge pull request #9 from uda/master
Minor doc changes
2014-09-23 15:59:42 +10:00
Yehuda Deutsch
afec12d163 Rename INSTALL to INSTALL.md 2014-09-21 11:11:07 +03:00
Yehuda Deutsch
a4a602b6ec Created README.md 2014-09-21 11:10:30 +03:00
Deon George
e1952cddb6 Merge pull request #6 from marclaporte/patch-2
typos
2014-09-18 12:32:56 +10:00
Deon George
ee415fe8c6 Merge pull request #5 from marclaporte/patch-1
typo
2014-09-18 12:32:08 +10:00
Deon George
eca5c4ea9f Merge pull request #8 from pteague/master
Modified posixAccount Shell selection
2014-09-18 12:31:19 +10:00
Patrick Teague
a01752a68c * Fixed posixAccount Shell so that 'Bash' is actually bash and not shell. Also added Shell, Dash, False, and No Login 2014-09-16 14:53:52 -05:00
Marc Laporte
ba90f86e7b typos 2014-07-25 23:04:40 -04:00
Marc Laporte
6135f94a51 typo 2014-07-25 20:36:21 -04:00
Deon George
f7c4bd311a Merge pull request #4 from ivdmeer/master
Bugfix: fixed call to renamed function pla_password_hash.
2014-06-05 13:00:27 +10:00
Ivo van der Meer
c736ecd8c2 Bugfix: fixed call to renamed function pla_password_hash. 2014-06-04 10:48:06 +02:00
Deon George
d2a800878f Merge pull request #3 from bchavet/master
Use preg_replace_callback instead of /e in preg_replace
2014-06-04 13:43:52 +10:00
Ben Chavet
5a7edc892f Use preg_replace_callback instead of /e in preg_replace to fix E_DEPRECATED warnings 2014-05-29 18:57:44 +00:00
Deon George
d258398b68 Merge pull request #2 from archayl/php55fix
Php55fix
2014-05-14 09:05:39 +10:00
Mohamad Elrashidin Bin Sajeli
b082cf1742 Changed preg_replace to preg_replace callback 2014-05-08 20:40:57 +08:00
Mohamad Elrashidin Bin Sajeli
e673df3ba8 Changed password_hash to pla_password_hash 2014-05-08 20:22:30 +08:00
Deon George
cfbee19721 Release 1.2.3 2012-10-01 16:54:14 +10:00
Deon George
092db24f99 Update template to show multiselect values 2012-10-01 16:47:53 +10:00
Deon George
927e515df3 Language update from launchpad for 1.2.3 (also see #30) 2012-09-06 13:00:06 +10:00
Deon George
bbedf18b7e SF Bug #3531956 - Search / Show Attributes must be lowercase 2012-09-05 22:44:46 +10:00
Deon George
f1ed59a35e SF Bug #3518548 - Missing attributes on some custom forms 2012-09-05 22:18:31 +10:00
Deon George
55fa21af26 SF Bug #3513210 - Export to VCARD only exports the last entry in the list 2012-09-05 21:57:17 +10:00
Deon George
f28d535948 SF Bug #3510648 - Cannot copy between servers 2012-09-05 21:54:42 +10:00
Deon George
2f70eb41b3 SF Bug #3510114 - Unable to check passwords when samba hashes are in lowercase 2012-09-05 21:25:50 +10:00
Deon George
6b9834a054 SF Bug #3452416 - templates <order> non-functional 2012-09-05 20:23:17 +10:00
Deon George
caf24e3662 SF Bug #3427748 - value id is ignored in select attribute 2012-09-05 20:02:14 +10:00
Roland Gruber
c4b6695beb SF Bug #3448530 - Treat krbExtraData and krbPrincipalKey as binary 2012-09-04 15:09:24 +10:00
Deon George
74434e5ca3 SF Bug #3497660 - XSS flaws via 'export', 'add_value_form' and 'dn' variables 2012-09-03 07:16:34 +10:00
Deon George
88d41216f9 SF Bug #3426575 - clicking 'logout' does not unset _SESSION['ACTIVITY'] 2012-09-03 06:19:19 +10:00
Paweł Tomulik
09c5e3a8da SF Feature #3555472 - User-friendly items in entry chooser window. 2012-09-01 11:43:14 +10:00
Jean-Philippe Ghibaudo
21959715c3 SF Feature #3509651 - Add support for SHA512 with OpenLDAP 2012-09-01 11:31:38 +10:00
Roland Gruber
3690ad16f0 SF Patch #3469148 - Display mass edit actions as buttons 2012-08-29 22:01:43 +10:00
Deon George
7dc8d57d69 SF Bug #3477910 - XSS vulnerability in query 2012-01-24 12:38:47 +11:00
Deon George
dece0f496f Release 1.2.2 2011-10-27 13:07:09 +11:00
Deon George
d58f011fbb Language Translation merge from launchpad 2011-10-27 13:06:53 +11:00
Deon George
696c266eee Additional fix for SF Feature #3387473 2011-10-27 12:55:24 +11:00
Caleb Callaway
2d018aad7b SF Feature #3387473 - Support for schema discovery using OpenLDAP's cn=config DN 2011-10-13 08:18:10 +11:00
Deon George
cddf783c27 Add an alert when RFC3866 tags are being used 2011-10-06 16:16:27 +11:00
Deon George
1e1fcabb3d SF Bug #3398344 - Import LDIF overwrites entries 2011-10-06 14:29:35 +11:00
Roland Gruber
d8ab7fc2f0 SF Patch #3391547 - Option for minmal mode 2011-10-06 12:31:12 +11:00
Roland Gruber
56830f1fa4 SF Patch #3391389 - Option to initially open the tree 2011-10-06 12:22:55 +11:00
Roland Gruber
6c8b623788 SF Patch #3391371 - Fix for schema link deactivation 2011-10-06 11:57:06 +11:00
Roland Gruber
7fc4f0c7e4 SF Patch #3391039 - Remove eval commands from PHP code 2011-10-06 11:43:40 +11:00
Deon George
059b83befb SF Bug #3391046 - Loading entries with many attributes is very slow 2011-10-06 11:06:43 +11:00
Deon George
4089ffa9fe SF Bug #3392644 - Cannot authenticate if password starts or ends with spaces 2011-10-06 10:40:41 +11:00
Deon George
c57a927311 Disable supplied modifiction templates, it confused too many people 2011-10-06 09:35:58 +11:00
Deon George
d5744b055a SF Bug #3370546 - AjaxEnabled create and delete entry fails on IE9 2011-10-06 09:12:54 +11:00
Deon George
76e6dad13e SF Bug #3417184 - PHP Code Injection Vulnerability 2011-10-06 09:03:20 +11:00
Deon George
5d4245f93a SF Bug #3395004 - config.php.example refers to lang/en.php 2011-09-08 22:51:02 +10:00
Deon George
80d027d569 SF Bug #3373466 - Unable to define force_may attributes 2011-09-08 22:30:35 +10:00
Deon George
64668e882b Remove XSS vulnerabilty in debug code 2011-07-27 07:30:06 +10:00
Felix Chelu
caeba72171 SF Bug #3355722 - Issue in MultiList attribute type 2011-07-07 23:45:21 +10:00
Deon George
07827304b7 SF Bug #3355732 - Cosmetic issue in functions.php -> get_icon() 2011-07-07 23:12:23 +10:00
Deon George
446faf78fb FIX SASL configuration example 2011-06-21 13:45:19 +10:00
Deon George
afa4a95b37 Fix SASL implementation - enabled GSSAPI 2011-06-20 20:34:55 +10:00
Deon George
5987194dec SF Bug #3304785 - posixGroup creation template uses cn instead of uid 2011-05-20 23:58:48 +10:00
Deon George
ddb5ed0346 Enabled hiding base DNs that users dont have access to 2011-05-20 23:53:39 +10:00
Deon George
7649b9b826 SF Feature #3298820 - Only custom templates 2011-05-14 10:42:12 +10:00
107 changed files with 1490 additions and 77960 deletions

View File

@@ -5,7 +5,7 @@ For install instructions in non-English languages, see the wiki:
phpLDAPadmin requires the following:
a. A web server (Apache, IIS, etc).
b. PHP 5.0.0 or newer (with LDAP support)
b. PHP 7.0.0 or newer (with LDAP support)
* To install

90
README.md Normal file
View File

@@ -0,0 +1,90 @@
# phpLDAPadmin
phpLDAPadmin is a web based LDAP data management tool for system administrators. It is commonly known and referred by many as "PLA".
A primary goal of PLA is to be as intuitive as possible - so it is certainly possible for end users to use it as well, for example, to manage their data in an LDAP server.
PLA is designed to be compliant with LDAP RFCs, enabling it to be used with any LDAP server.
If you come across an LDAP server, where PLA exhibits problems, please open an issue with full details of the problem so that we can have it fixed.
## History
Initially created in 2002 by David Smith, it was taken over by Deon George (aka leenooks) in 2005.
Since 2003 many things have changed - initial development was done in CVS and the project was hosted on Sourceforge.
In 2009, CVS was swapped out for GIT, and in around 2011 the project was moved to Github.
The PLA v1.2.x stream was created in July 2009.
Work on PLA v2 has started and some information on that is below. Soon `master` will be updated and `BRANCH-2.0` will be visible in git. Until then, a sneak peak of v2 is available [here](https://phpldapadmin.servio.leenooks.net)
## THANK YOU
Over the years, many, many, many people have supported PLA with either their time, their coding or with financial donations.
I have tried to send an email to acknowledge each contribution, and if you havent seen anything personally from me, I am sorry, but please know that I do appreciate all the help I get, in whatever form it is provided.
Again, Thank You.
## Future
Web development, tools, approaches and technology has come along way since 2009 and some talented folks have created some fantastic tools.
With that PLA is going under a major revamp in preparation for v2 and will aim to use those existing creations to help speed up the revamp effort.
Some of the creations planned to be used in v2 include:
* Laravel (https://laravel.com)
* adldap2/adldap2 (https://github.com/Adldap2/Adldap2)
* JQuery (https://jquery.com)
* FancyTree (https://github.com/mar10/fancytree)
* ArchitectUI (https://architectui.com)
PLA v1.2.x will be archived into [BRANCH-1.2](https://github.com/leenooks/phpLDAPadmin/tree/BRANCH-1.2), and `master` will be changed to reflect the new v2 work and effort.
If you plan to use PLA, and cannot use an installation from your OS package, please use [BRANCH-1.2](https://github.com/leenooks/phpLDAPadmin/tree/BRANCH-1.2) while progress is made in master for v2.
If you like the cutting edge, feel free to try out `master`, but expect problems, bugs and missing functionality.
If you have extended v2 and would like to contribute your extension, or if you find a way to fix something that is broken or missing please submit a pull request.
Alternatively, you can get take a peek at the work so far by using our docker container, which is built automatically after testing passes.
The [demo](http://demo.phpldapadmin.org) site, will also be running the same docker container. (See below for details.)
In summary, for the time being, expect `master` to be buggy and broken, and I'll update this readme as enhancements progress.
## Installation
The following instructions will be for PLA v2 when its commited to GIT. Checkback regularly, as it will be pushed when its is semi functional.
### Installation on your server
#### Prerequisites
* A HTTP server (eg: Apache, Nginx)
* PHP (minimum version 7.2) https://www.php.net
* Composer https://getcomposer.org
* GIT
#### Installation
1. Checkout the code from github
```bash
git clone https://github.com/leenooks/phpLDAPadmin.git
```
1. Install composer dependencies.
```bash
composer install
```
1. Edit your `.env` file as appropriate
copy `.env.example` to `.env` as a start.
1. Configure your webserver to have PLA's root in the `public` directory
### Using Docker
Instructions to come.
## Getting Help
The best place to get help with PLA (new and old) is on Stack Overflow (https://stackoverflow.com/tags/phpldapadmin/info)
## Found a bug?
If you have found a bug, and can provide detailed instructions so that it can be reproduced, please open an [issue](https://github.com/leenooks/phpLDAPadmin/issues) and provide those details.
Before opening a ticket, please check to see if it hasnt already been reported, and if it has, please provide any additional information that will help it be fixed.
*TIP*: Issues opened with reproducible details accompanied with a patch (or a pull request) to fix the problem will be looked at first.
## License
[LICENSE](LICENSE)

View File

@@ -1 +1 @@
RELEASE-1.2.1.1
RELEASE-1.2.6.6

View File

@@ -53,10 +53,11 @@
// $config->custom->session['http_realm'] = sprintf('%s %s',app_name(),'login');
/* The language setting. If you set this to 'auto', phpLDAPadmin will attempt
to determine your language automatically. Otherwise, available lanaguages
are: 'ct', 'de', 'en', 'es', 'fr', 'it', 'nl', and 'ru'
Localization is not complete yet, but most strings have been translated.
Please help by writing language files. See lang/en.php for an example. */
to determine your language automatically.
If PLA doesnt show (all) strings in your language, then you can do some
translation at http://translations.launchpad.net/phpldapadmin and download
the translation files, replacing those provided with PLA.
(We'll pick up the translations before making the next release too!) */
// $config->custom->appearance['language'] = 'auto';
/* The temporary storage directory where we will put jpegPhoto data
@@ -70,6 +71,33 @@
environments. */
# $config->custom->password['no_random_crypt_salt'] = true;
/* If you want to restrict password available types (encryption algorithms)
Should be subset of:
array(
''=>'clear',
'bcrypt'=>'bcrypt',
'blowfish'=>'blowfish',
'crypt'=>'crypt',
'ext_des'=>'ext_des',
'md5'=>'md5',
'k5key'=>'k5key',
'md5crypt'=>'md5crypt',
'sha'=>'sha',
'smd5'=>'smd5',
'ssha'=>'ssha',
'sha256'=>'sha256',
'ssha256'=>'ssha256',
'sha384'=>'sha384',
'ssha384'=>'ssha384',
'sha512'=>'sha512',
'ssha512'=>'ssha512',
'sha256crypt'=>'sha256crypt',
'sha512crypt'=>'sha512crypt',
'argon2i'=>'argon2i',
'argon2id'=>'argon2id',
)*/
# $config->custom->password['available_types'] = array(''=>'clear','md5'=>'md5');
/* PHP script timeout control. If php runs longer than this many seconds then
PHP will stop with an Maximum Execution time error. Increase this value from
the default if queries to your LDAP server are slow. The default is either
@@ -159,6 +187,9 @@ $config->custom->commands['script'] = array(
/* Hide the warnings for invalid objectClasses/attributes in templates. */
// $config->custom->appearance['hide_template_warning'] = false;
/* Set to true if you would like to hide header and footer parts. */
// $config->custom->appearance['minimalMode'] = false;
/* Configure what objects are shown in left hand tree */
// $config->custom->appearance['tree_filter'] = '(objectclass=*)';
@@ -169,6 +200,10 @@ $config->custom->commands['script'] = array(
// $config->custom->appearance['tree_width'] = null;
# $config->custom->appearance['tree_width'] = 250;
/* Number of tree command icons to show, 0 = show all icons on 1 row. */
// $config->custom->appearance['tree_icons'] = 0;
# $config->custom->appearance['tree_icons'] = 4;
/* Confirm create and update operations, allowing you to review the changes
and optionally skip attributes during the create/update operation. */
// $config->custom->confirm['create'] = true;
@@ -231,7 +266,7 @@ $config->custom->appearance['friendly_attrs'] = array(
*********************************************/
/* Add "modify group members" link to the attribute. */
// $config->custom->modify_member['groupattr'] = array('member','uniqueMember','memberUid');
// $config->custom->modify_member['groupattr'] = array('member','uniqueMember','memberUid','sudoUser');
/* Configure filter for member search. This only applies to "modify group members" feature */
// $config->custom->modify_member['filter'] = '(objectclass=Person)';
@@ -295,7 +330,7 @@ $servers->setValue('server','name','My LDAP Server');
auto-detect it for you. */
// $servers->setValue('server','base',array(''));
/* Four options for auth_type:
/* Five options for auth_type:
1. 'cookie': you will login via a web form, and a client-side cookie will
store your login dn and password.
2. 'session': same as cookie but your login dn and password are stored on the
@@ -304,6 +339,9 @@ $servers->setValue('server','name','My LDAP Server');
HTTP authentication.
4. 'config': specify your login dn and password here in this config file. No
login will be required to use phpLDAPadmin for this server.
5. 'sasl': login will be taken from the webserver's kerberos authentication.
Currently only GSSAPI has been tested (using mod_auth_kerb).
6. 'sasl_external': login will be taken from SASL external mechanism.
Choose wisely to protect your authentication information appropriately for
your situation. If you choose 'cookie', your cookie contents will be
@@ -312,10 +350,11 @@ $servers->setValue('server','name','My LDAP Server');
// $servers->setValue('login','auth_type','session');
/* The DN of the user for phpLDAPadmin to bind with. For anonymous binds or
'cookie' or 'session' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS BLANK. If
you specify a login_attr in conjunction with a cookie or session auth_type,
then you can also specify the bind_id/bind_pass here for searching the
directory for users (ie, if your LDAP server does not allow anonymous binds. */
'cookie','session' or 'sasl' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS
BLANK. If you specify a login_attr in conjunction with a cookie or session
auth_type, then you can also specify the bind_id/bind_pass here for searching
the directory for users (ie, if your LDAP server does not allow anonymous
binds. */
// $servers->setValue('login','bind_id','');
# $servers->setValue('login','bind_id','cn=Manager,dc=example,dc=com');
@@ -327,6 +366,22 @@ $servers->setValue('server','name','My LDAP Server');
/* Use TLS (Transport Layer Security) to connect to the LDAP server. */
// $servers->setValue('server','tls',false);
/* TLS Certificate Authority file (overrides ldap.conf, PHP 7.1+) */
// $servers->setValue('server','tls_cacert',null);
# $servers->setValue('server','tls_cacert','/etc/openldap/certs/ca.crt');
/* TLS Certificate Authority hashed directory (overrides ldap.conf, PHP 7.1+) */
// $servers->setValue('server','tls_cacertdir',null);
# $servers->setValue('server','tls_cacertdir','/etc/openldap/certs');
/* TLS Client Certificate file (PHP 7.1+) */
// $servers->setValue('server','tls_cert',null);
# $servers->setValue('server','tls_cert','/etc/pki/tls/certs/ldap_user.crt');
/* TLS Client Certificate Key file (PHP 7.1+) */
// $servers->setValue('server','tls_key',null);
# $servers->setValue('server','tls_key','/etc/pki/tls/private/ldap_user.key');
/************************************
* SASL Authentication *
************************************/
@@ -334,22 +389,30 @@ $servers->setValue('server','name','My LDAP Server');
/* Enable SASL authentication LDAP SASL authentication requires PHP 5.x
configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to
false), then all other sasl options are ignored. */
// $servers->setValue('server','sasl_auth',false);
# $servers->setValue('login','auth_type','sasl');
/* SASL auth mechanism */
// $servers->setValue('server','sasl_mech','PLAIN');
/* SASL GSSAPI auth mechanism (requires auth_type of sasl) */
// $servers->setValue('sasl','mech','GSSAPI');
/* SASL PLAIN support... this mech converts simple binds to SASL
PLAIN binds using any auth_type (or other bind_id/pass) as credentials.
NOTE: auth_type must be simple auth compatible (ie not sasl) */
# $servers->setValue('sasl','mech','PLAIN');
/* SASL EXTERNAL support... really a different auth_type */
# $servers->setValue('login','auth_type','sasl_external');
/* SASL authentication realm name */
// $servers->setValue('server','sasl_realm','');
# $servers->setValue('server','sasl_realm','example.com');
// $servers->setValue('sasl','realm','');
# $servers->setValue('sasl','realm','EXAMPLE.COM');
/* SASL authorization ID name
If this option is undefined, authorization id will be computed from bind DN,
using sasl_authz_id_regex and sasl_authz_id_replacement. */
// $servers->setValue('server','sasl_authz_id', null);
using authz_id_regex and authz_id_replacement. */
// $servers->setValue('sasl','authz_id', null);
/* SASL authorization id regex and replacement
When sasl_authz_id property is not set (default), phpLDAPAdmin will try to
When authz_id property is not set (default), phpLDAPAdmin will try to
figure out authorization id by itself from bind distinguished name (DN).
This procedure is done by calling preg_replace() php function in the
@@ -361,18 +424,18 @@ $servers->setValue('server','name','My LDAP Server');
For info about pcre regexes, see:
- pcre(3), perlre(3)
- http://www.php.net/preg_replace */
// $servers->setValue('server','sasl_authz_id_regex',null);
// $servers->setValue('server','sasl_authz_id_replacement',null);
# $servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i');
# $servers->setValue('server','sasl_authz_id_replacement','$1');
// $servers->setValue('sasl','authz_id_regex',null);
// $servers->setValue('sasl','authz_id_replacement',null);
# $servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i');
# $servers->setValue('sasl','authz_id_replacement','$1');
/* SASL auth security props.
See http://beepcore-tcl.sourceforge.net/tclsasl.html#anchor5 for explanation. */
// $servers->setValue('server','sasl_props',null);
// $servers->setValue('sasl','props',null);
/* Default password hashing algorithm. One of md5, ssha, sha, md5crpyt, smd5,
blowfish, crypt or leave blank for now default algorithm. */
// $servers->setValue('appearance','password_hash','md5');
// $servers->setValue('appearance','pla_password_hash','md5');
/* If you specified 'cookie' or 'session' as the auth_type above, you can
optionally specify here an attribute to use when logging in. If you enter
@@ -393,6 +456,12 @@ $servers->setValue('server','name','My LDAP Server');
setup. */
// $servers->setValue('login','class',array());
/* If login_attr was set to 'dn', it is possible to specify a template string to
build the DN from. Use '%s' where user input should be inserted. A user may
still enter the complete DN. In this case the template will not be used. */
// $servers->setValue('login','bind_dn_template',null);
# $servers->setValue('login','bind_dn_template','cn=%s,ou=people,dc=example,dc=com');
/* If you specified something different from 'dn', for example 'uid', as the
login_attr above, you can optionally specify here to fall back to
authentication with dn.
@@ -410,6 +479,12 @@ $servers->setValue('server','name','My LDAP Server');
in the tree viewer. */
// $servers->setValue('appearance','show_create',true);
/* Set to true if you would like to initially open the first level of each tree. */
// $servers->setValue('appearance','open_tree',false);
/* Set to true to display authorization ID in place of login dn (PHP 7.2+) */
// $servers->setValue('appearance','show_authz',false);
/* This feature allows phpLDAPadmin to automatically determine the next
available uidNumber for a new entry. */
// $servers->setValue('auto_number','enable',true);
@@ -458,6 +533,11 @@ $servers->setValue('server','name','My LDAP Server');
/* Set this if you dont want this LDAP server to show in the tree */
// $servers->setValue('server','visible',true);
/* Set this if you want to hide the base DNs that dont exist instead of
displaying the message "The base entry doesnt exist, create it?"
// $servers->setValue('server','hide_noaccess_base',false);
# $servers->setValue('server','hide_noaccess_base',true);
/* This is the time out value in minutes for the server. After as many minutes
of inactivity you will be automatically logged out. If not set, the default
value will be ( session_cache_expire()-1 ) */
@@ -483,8 +563,8 @@ $servers->setValue('server','name','My LDAP Server');
server may automatically calculate a default value.
In Fedora Directory Server using the DNA Plugin one could ignore uidNumber,
gidNumber and sambaSID. */
// $servers->setValue('force_may','attrs',array(''));
# $servers->setValue('force_may','attrs',array('uidNumber','gidNumber','sambaSID'));
// $servers->setValue('server','force_may',array(''));
# $servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID'));
/*********************************************
* Unique attributes *
@@ -523,15 +603,15 @@ $servers->setValue('login','bind_pass','');
$servers->setValue('server','tls',false);
# SASL auth
$servers->setValue('server','sasl_auth',true);
$servers->setValue('server','sasl_mech','PLAIN');
$servers->setValue('server','sasl_realm','EXAMPLE.COM');
$servers->setValue('server','sasl_authz_id',null);
$servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i');
$servers->setValue('server','sasl_authz_id_replacement','$1');
$servers->setValue('server','sasl_props',null);
$servers->setValue('login','auth_type','sasl');
$servers->setValue('sasl','mech','GSSAPI');
$servers->setValue('sasl','realm','EXAMPLE.COM');
$servers->setValue('sasl','authz_id',null);
$servers->setValue('sasl','authz_id_regex','/^uid=([^,]+)(.+)/i');
$servers->setValue('sasl','authz_id_replacement','$1');
$servers->setValue('sasl','props',null);
$servers->setValue('appearance','password_hash','md5');
$servers->setValue('appearance','pla_password_hash','md5');
$servers->setValue('login','attr','dn');
$servers->setValue('login','fallback_dn',false);
$servers->setValue('login','class',null);
@@ -556,6 +636,21 @@ $servers->setValue('login','timeout',30);
$servers->setValue('server','branch_rename',false);
$servers->setValue('server','custom_sys_attrs',array('passwordExpirationTime','passwordAllowChangeTime'));
$servers->setValue('server','custom_attrs',array('nsRoleDN','nsRole','nsAccountLock'));
$servers->setValue('force_may','attrs',array('uidNumber','gidNumber','sambaSID'));
$servers->setValue('server','force_may',array('uidNumber','gidNumber','sambaSID'));
*/
/***********************************************************************************
* If you want to configure Google reCAPTCHA on autentication form, do so below. *
* Remove the commented lines and use this section as a template for all *
* reCAPTCHA v2 Generate on https://www.google.com/recaptcha/ *
* *
* IMPORTANT: Select reCAPTCHA v2 on Type of reCAPTCHA *
***********************************************************************************/
$config->custom->session['reCAPTCHA-enable'] = false;
$config->custom->session['reCAPTCHA-key-site'] = '<put-here-key-site>';
$config->custom->session['reCAPTCHA-key-server'] = '<put-here-key-server>';
?>

View File

@@ -1,2 +1,2 @@
Please see http://phpldapadmin.sourceforge.net/Translate now for information on
Please see http://phpldapadmin.sourceforge.net/wiki/index.php/Translate now for information on
translating PLA.

View File

@@ -80,6 +80,9 @@ index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub
sasl-regexp uid=(.*),cn=(.*),cn=gssapi,cn=auth
ldap:///dc=example.com??sub?(&(uid=$1)(objectClass=inetOrgPerson))
database bdb
suffix "o=Flintstones"
rootdn "cn=Manager,o=Flintstones"

View File

@@ -34,7 +34,7 @@ if ($request['attribute']->isReadOnly())
# Render the form
if (! strcasecmp($request['attr'],'objectclass') || get_request('meth','REQUEST') != 'ajax') {
# Render the form.
$request['page']->drawTitle(sprintf('%s <b>%s</b> %s <b>%s</b>',_('Add new'),$request['attr'],_('value to'),get_rdn($request['dn'])));
$request['page']->drawTitle(sprintf('%s <b>%s</b> %s <b>%s</b>',_('Add new'),htmlspecialchars($request['attr']),_('value to'),htmlspecialchars(get_rdn($request['dn']))));
$request['page']->drawSubTitle();
if (! strcasecmp($request['attr'],'objectclass')) {

View File

@@ -19,10 +19,6 @@ $www['meth'] = get_request('meth','REQUEST');
ob_start();
switch ($www['cmd']) {
case '_debug':
debug_dump($_REQUEST,1);
break;
default:
if (defined('HOOKSDIR') && file_exists(HOOKSDIR.$www['cmd'].'.php'))
$app['script_cmd'] = HOOKSDIR.$www['cmd'].'.php';
@@ -45,7 +41,7 @@ if (DEBUG_ENABLED)
$www['page'] = new page($app['server']->getIndex());
# See if we can render the command
if (trim($www['cmd'])) {
if ($www['cmd'] && trim($www['cmd'])) {
# If this is a READ-WRITE operation, the LDAP server must not be in READ-ONLY mode.
if ($app['server']->isReadOnly() && ! in_array(get_request('cmd','REQUEST'),$app['readwrite_cmds']))
error(_('You cannot perform updates while server is in read-only mode'),'error','index.php');

View File

@@ -19,7 +19,7 @@ $dn = get_request('dn','GET',true);
$tree = get_cached_item($app['server']->getIndex(),'tree');
$entry = $tree->getEntry($dn);
$entry->close();
set_cached_item($app['server']->getIndex(),'tree','null',$tree);
set_cached_item($app['server']->getIndex(),$tree,'tree','null');
header(sprintf('Location:index.php?server_id=%s&junk=%s#%s%s',
$app['server']->getIndex(),random_junk(),htmlid($app['server']->getIndex(),$dn),app_session_param()));

View File

@@ -41,7 +41,7 @@ $request['recursive'] = (get_request('recursive') == 'on') ? true : false;
$request['remove'] = (get_request('remove') == 'yes') ? true : false;
if ($request['recursive']) {
$filter = get_request('filter','POST',false,'(objectClass=*)');
$filter = get_request('filter','POST',false,'(objectClass=*)',false);
# Build a tree similar to that of the tree browser to give to r_copy_dn
$ldap['tree'] = array();
@@ -63,12 +63,12 @@ if ($request['recursive']) {
print '</small>';
} else {
if ($_SESSION[APPCONFIG]->getValue('confirm','copy')) {
$request['pageSRC'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,null));
if ($_SESSION[APPCONFIG]->getValue('confirm','copy') && !$request['remove']) {
$request['pageSRC'] = new TemplateRender($ldap['SRC']->getIndex(),get_request('template','REQUEST',false,null));
$request['pageSRC']->setDN($request['dnSRC']);
$request['pageSRC']->accept(true);
$request['pageDST'] = new TemplateRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none'));
$request['pageDST'] = new TemplateRender($ldap['DST']->getIndex(),get_request('template','REQUEST',false,'none'));
$request['pageDST']->setContainer($app['server']->getContainer($request['dnDST']));
$request['pageDST']->accept(true);

View File

@@ -46,8 +46,7 @@ if (! $request['template']->getRDN())
# Some other attribute checking...
foreach ($request['template']->getAttributes() as $attribute) {
# Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through.
# @todo this isIgnoredAttr() function is missing?
if ($attribute->isRequired() && ! count($attribute->getValues()) && ! $app['server']->isIgnoredAttr($attr->getName()))
if ($attribute->isRequired() && ! count($attribute->getValues()))
error(sprintf(_('You left the value blank for required attribute (%s).'),
$attribute->getName(false)),'error','index.php');
}

View File

@@ -40,8 +40,7 @@ if (! $request['template']->getRDN())
# Some other attribute checking...
foreach ($request['template']->getAttributes() as $attribute) {
# Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through.
# @todo this isIgnoredAttr() function is missing?
if ($attribute->isRequired() && ! count($attribute->getValues()) && ! $app['server']->isIgnoredAttr($attr->getName()))
if ($attribute->isRequired() && ! count($attribute->getValues()))
error(sprintf(_('You left the value blank for required attribute (%s).'),
$attribute->getName(false)),'error','index.php');
}

View File

@@ -50,7 +50,7 @@ if ($request['dn']) {
}
if ($treesave)
set_cached_item($app['server']->getIndex(),'tree','null',$tree);
set_cached_item($app['server']->getIndex(),$tree,'tree','null');
if ($request['dn'])
echo $tree->draw_children($dnentry,$request['code']);

View File

@@ -15,9 +15,9 @@ $www['page'] = new page();
$request = array();
$request['container'] = get_request('container','GET');
$request['form'] = get_request('form','GET');
$request['element'] = get_request('element','GET');
$request['rdn'] = get_request('rdn','GET');
$request['form'] = htmlspecialchars(addslashes(get_request('form','GET')));
$request['element'] = htmlspecialchars(addslashes(get_request('element','GET')));
$request['rdn'] = htmlspecialchars(addslashes(get_request('rdn','GET')));
echo '<div class="popup">';
printf('<h3 class="subtitle">%s</h3>',_('Entry Chooser'));
@@ -33,12 +33,13 @@ echo '</script>';
echo '<table class="forminput" width="100%" border="0">';
if ($request['container']) {
printf('<tr><td class="heading" colspan="3">%s:</td><td>%s</td></tr>',_('Server'),$app['server']->getName());
printf('<tr><td class="heading" colspan="3">%s:</td><td>%s</td></tr>',_('Looking in'),$request['container']);
printf('<tr><td class="heading" colspan="3">%s:</td><td>%s</td></tr>',_('Looking in'),htmlspecialchars($request['container']));
echo '<tr><td class="blank" colspan="4">&nbsp;</td></tr>';
}
# Has the user already begun to descend into a specific server tree?
if (isset($app['server']) && ! is_null($request['container'])) {
$tree = get_cached_item($app['server']->getIndex(),'tree');
$request['children'] = $app['server']->getContainerContents($request['container'],null,0,'(objectClass=*)',$_SESSION[APPCONFIG]->getValue('deref','tree'));
sort($request['children']);
@@ -78,7 +79,18 @@ if (isset($app['server']) && ! is_null($request['container'])) {
echo '<td class="blank">&nbsp;</td>';
printf('<td class="icon"><a href="%s"><img src="%s/plus.png" alt="Plus" /></a></td>',$href['expand'],IMGDIR);
printf('<td colspan="2"><a href="%s">%s</a></td>',$href['return'],$dn);
$entry = $tree->getEntry($dn);
if (is_null($entry)) {
$tree->addEntry($dn);
$entry = $tree->getEntry($dn);
}
if ($entry)
$item = draw_formatted_dn($app['server'], $entry);
else
$item = $dn;
printf('<td colspan="2"><a href="%s">%s</a></td>',$href['return'], $item );
echo '</tr>';
echo "\n\n";
}

View File

@@ -19,7 +19,7 @@ $dn = get_request('dn','GET',true);
$tree = get_cached_item($app['server']->getIndex(),'tree');
$entry = $tree->getEntry($dn);
$entry->open();
set_cached_item($app['server']->getIndex(),'tree','null',$tree);
set_cached_item($app['server']->getIndex(),$tree,'tree','null');
header(sprintf('Location:index.php?server_id=%s&junk=%s#%s%s',
$app['server']->getIndex(),random_junk(),htmlid($app['server']->getIndex(),$dn),app_session_param()));

View File

@@ -29,12 +29,12 @@ if ($request['file']) {
header('Content-type: application/download');
header(sprintf('Content-Disposition: inline; filename="%s.%s"','export',$types['extension'].($request['export']->isCompressed() ? '.gz' : '')));
$request['export']->export();
echo $request['export']->export();
die();
} else {
print '<span style="font-size: 14px; font-family: courier;"><pre>';
$request['export']->export();
echo htmlspecialchars($request['export']->export());
print '</pre></span>';
}
?>

View File

@@ -13,11 +13,11 @@ require './common.php';
require LIBDIR.'export_functions.php';
$request = array();
$request['dn'] = get_request('dn','GET');
$request['dn'] = get_request('dn','GET',false,'');
$request['format'] = get_request('format','GET',false,get_line_end_format());
$request['scope'] = get_request('scope','GET',false,'base');
$request['exporter_id'] = get_request('exporter_id','GET',false,'LDIF');
$request['filter'] = get_request('filter','GET',false,'(objectClass=*)');
$request['filter'] = get_request('filter','GET',false,'(objectClass=*)',false);
$request['attr'] = get_request('attributes','GET',false,'*');
$request['sys_attr'] = get_request('sys_attr','GET') ? true: false;
@@ -81,7 +81,7 @@ printf('<tr><td>%s</td><td><input type="text" name="filter" style="width:300px"
_('Search Filter'),htmlspecialchars($request['filter']));
printf('<tr><td>%s</td><td><input type="text" name="attributes" style="width:300px" value="%s" /></td></tr>',
_('Show Attributtes'),htmlspecialchars($request['attr']));
_('Show Attributes'),htmlspecialchars($request['attr']));
printf('<tr><td>&nbsp;</td><td><input type="checkbox" name="sys_attr" id="sys_attr" %s/> <label for="sys_attr">%s</label></td></tr>',
$request['sys_attr'] ? 'checked="checked" ' : '',_('Include system attributes'));

View File

@@ -57,6 +57,11 @@ if (defined('CONFDIR'))
else
$app['config_file'] = 'config.php';
if (! is_readable($app['config_file'])) {
if (ob_get_level()) ob_end_clean();
die(sprintf("Missing configuration file <b>%s</b> - have you created it?",$app['config_file']));
}
# Make sure this PHP install has session support
if (! extension_loaded('session'))
error('<p>Your install of PHP appears to be missing php-session support.</p><p>Please install php-session support before using phpLDAPadmin.<br /><small>(Dont forget to restart your web server afterwards)</small></p>','error',null,true);
@@ -120,8 +125,10 @@ if (! $config = check_config($app['config_file'])) {
$_SESSION[APPCONFIG] = $config;
}
if ($uri = get_request('URI','GET'))
if ($uri = get_request('URI','GET')) {
header(sprintf('Location: cmd.php?%s',base64_decode($uri)));
exit;
}
if (! preg_match('/^([0-9]+\.?)+/',app_version())) {
system_message(array(

View File

@@ -15,13 +15,13 @@ function ajSUBMIT(div,obj,display) {
window.scrollTo(0,95);
makeHttpRequest('cmd.php',getParameters(obj.parentNode)+'meth=ajax','POST','alertAJ','cancelAJ',div);
if (pageDiv)
includeHTML(pageDiv,'<img src="images/ajax-progress.gif"><br><small>'+display+'...</small>');
else
return true;
makeHttpRequest('cmd.php',getParameters(obj.parentNode)+'meth=ajax','POST','alertAJ','cancelAJ',div);
return false;
}
@@ -31,13 +31,13 @@ function ajDISPLAY(div,urlParameters,display,ns) {
if (! ns)
window.scrollTo(0,95);
makeHttpRequest('cmd.php',urlParameters+'&meth=ajax','GET','alertAJ','cancelAJ',div);
if (pageDiv)
includeHTML(pageDiv,'<img src="images/ajax-progress.gif"><br><small>'+display+'...</small>');
else
return true;
makeHttpRequest('cmd.php',urlParameters+'&meth=ajax','GET','alertAJ','cancelAJ',div);
return false;
}
@@ -202,8 +202,6 @@ function makeHttpRequest(url,parameters,meth,successCallbackFunctionName,errorCa
http_request.open(meth,url,true);
http_request.setRequestHeader('Content-type','application/x-www-form-urlencoded');
http_request.setRequestHeader('Content-length',parameters.length);
http_request.setRequestHeader('Connection','close');
if (meth == 'GET') parameters = null;
http_request.send(parameters);

View File

@@ -11,27 +11,44 @@
require './common.php';
$user = array();
$user['login'] = get_request('login');
$user['password'] = get_request('login_pass');
$pass = true;
if ($_SESSION[APPCONFIG]->getValue('session', 'reCAPTCHA-enable')) {
$pass = !IsRobot(get_request('g-recaptcha-response'));
}
if ($user['login'] && ! strlen($user['password']))
system_message(array(
'title'=>_('Authenticate to server'),
'body'=>_('You left the password blank.'),
'type'=>'warn'),
sprintf('cmd.php?cmd=login_form&server_id=%s',get_request('server_id','REQUEST')));
if ($pass) {
$user = array();
$user['login'] = get_request('login');
$user['password'] = get_request('login_pass', 'POST', false, '', false);
if ($user['login'] && !strlen($user['password'])) {
system_message(array(
'title' => _('Authenticate to server'),
'body' => _('You left the password blank.'),
'type' => 'warn'),
sprintf('cmd.php?cmd=login_form&server_id=%s', get_request('server_id', 'REQUEST')));
}
if ($app['server']->login($user['login'], $user['password'], 'user')) {
system_message(array(
'title' => _('Authenticate to server'),
'body' => _('Successfully logged into server.'),
'type' => 'info'),
sprintf('cmd.php?server_id=%s', get_request('server_id', 'REQUEST')));
} else {
system_message(array(
'title' => _('Failed to Authenticate to server'),
'body' => _('Invalid Username or Password.'),
'type' => 'error'),
sprintf('cmd.php?cmd=login_form&server_id=%s', get_request('server_id', 'REQUEST')));
}
} else {
system_message(array(
'title' => _('Authenticate to server'),
'body' => _('Incorrect captcha.'),
'type' => 'warn'),
sprintf('cmd.php?cmd=login_form&server_id=%s', get_request('server_id', 'REQUEST')));
}
if ($app['server']->login($user['login'],$user['password'],'user'))
system_message(array(
'title'=>_('Authenticate to server'),
'body'=>_('Successfully logged into server.'),
'type'=>'info'),
sprintf('cmd.php?server_id=%s',get_request('server_id','REQUEST')));
else
system_message(array(
'title'=>_('Failed to Authenticate to server'),
'body'=>_('Invalid Username or Password.'),
'type'=>'error'),
sprintf('cmd.php?cmd=login_form&server_id=%s',get_request('server_id','REQUEST')));
?>

View File

@@ -16,7 +16,19 @@ printf('<h3 class="title">%s %s</h3>',_('Authenticate to server'),$app['server']
echo '<br />';
# Check for a secure connection
if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') {
$isHTTPS = false;
# Check if the current connection is encrypted
if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
$isHTTPS = true;
}
# Check if a proxy server downstream does encryption for us
elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && strtolower($_SERVER['HTTP_X_FORWARDED_SSL'])
== 'on') {
$isHTTPS = true;
}
if (!$isHTTPS) {
echo '<div style="text-align: center; color:red">';
printf('<acronym title="%s"><b>%s: %s.</b></acronym>',
_('You are not using \'https\'. Web browser will transmit login information in clear text.'),
@@ -25,6 +37,7 @@ if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') {
echo '<br />';
}
unset($isSecure);
# HTTP Basic Auth Form.
if ($app['server']->getAuthType() == 'http') {
@@ -52,7 +65,7 @@ if ($app['server']->getAuthType() == 'http') {
# HTML Login Form
} else {
echo '<form action="cmd.php" method="post">';
echo '<form action="cmd.php" method="post" autocomplete="off">';
echo '<div>';
echo '<input type="hidden" name="cmd" value="login" />';
printf('<input type="hidden" name="server_id" value="%s" />',$app['server']->getIndex());
@@ -67,7 +80,7 @@ if ($app['server']->getAuthType() == 'http') {
printf('<tr><td><b>%s:</b></td></tr>',
$app['server']->getValue('login','auth_text') ? $app['server']->getValue('login','auth_text') :
($app['server']->getValue('login','attr') == 'dn' ? _('Login DN') : $_SESSION[APPCONFIG]->getFriendlyName($app['server']->getValue('login','attr'))));
($app['server']->getValue('login','attr') == 'dn' ? ($app['server']->getValue('login', 'bind_dn_template') ? _('User Name') . ' / ' . _('Login DN') : _('Login DN')) : $_SESSION[APPCONFIG]->getFriendlyName($app['server']->getValue('login','attr'))));
printf('<tr><td><input type="text" id="login" name="login" size="40" value="%s" /></td></tr>',
$app['server']->getValue('login','attr',false) == 'dn' ? $app['server']->getValue('login','bind_id') : '');
@@ -77,6 +90,13 @@ if ($app['server']->getAuthType() == 'http') {
echo '<tr><td><input type="password" id="password" size="40" value="" name="login_pass" /></td></tr>';
echo '<tr><td colspan="2">&nbsp;</td></tr>';
#reCAPTCHA
if ($_SESSION[APPCONFIG]->getValue('session', 'reCAPTCHA-enable')) {
echo '<script src="https://www.google.com/recaptcha/api.js"></script>';
echo '<tr><td><div class="g-recaptcha" data-sitekey="'.$_SESSION[APPCONFIG]->getValue('session', 'reCAPTCHA-key-site').'"></div></td></tr>';
echo '<tr><td colspan="2">&nbsp;</td></tr>';
}
# If Anon bind allowed, then disable the form if the user choose to bind anonymously.
if ($app['server']->isAnonBindAllowed())
printf('<tr><td colspan="2"><small><b>%s</b></small> <input type="checkbox" name="anonymous_bind" onclick="form_field_toggle_enable(this,[\'login\',\'password\'],\'login\')" id="anonymous_bind_checkbox" /></td></tr>',

View File

@@ -11,13 +11,16 @@
require './common.php';
if ($app['server']->logout())
if ($app['server']->logout()) {
unset($_SESSION['ACTIVITY'][$app['server']->getIndex()]);
system_message(array(
'title'=>_('Authenticate to server'),
'title'=>_('Logout from Server'),
'body'=>_('Successfully logged out of server.'),
'type'=>'info'),
sprintf('index.php?server_id=%s',$app['server']->getIndex()));
else
} else
system_message(array(
'title'=>_('Failed to Logout of server'),
'body'=>_('Please report this error to the admins.'),

View File

@@ -129,15 +129,15 @@ foreach (array(
}
# cn=Connections,cn=Monitor
printf('<tr class="list_item"><td class="heading" rowspan="2"><acronym title="%s">%s</acronym></td></tr>',$results['cn=Connections,cn=Monitor']['description'],_('LDAP Connections'));
printf('<tr class="list_item"><td class="heading" rowspan="2"><acronym title="%s">%s</acronym></td></tr>',$results['cn=Connections,cn=Monitor']['description'][0],_('LDAP Connections'));
printf('<tr class="list_item"><td class="value">');
echo '<table class="result"><tr><td>';
echo '<table class="result_table" border="0" width="100%">';
printf('<tr class="highlight"><td class="20%%">%s</td><td class="value" style="width: 80%%;">%s</td></tr>',
_('Total Connections'),$results['cn=Total,cn=Connections,cn=Monitor']['monitorcounter']);
_('Total Connections'),$results['cn=Total,cn=Connections,cn=Monitor']['monitorcounter'][0]);
printf('<tr class="highlight"><td class="20%%">%s</td><td class="value" style="width: 80%%;">%s</td></tr>',
_('Current Connections'),$results['cn=Current,cn=Connections,cn=Monitor']['monitorcounter']);
_('Current Connections'),$results['cn=Current,cn=Connections,cn=Monitor']['monitorcounter'][0]);
# Look for some connections
foreach ($results as $key => $value) {

View File

@@ -15,8 +15,8 @@ $www['page'] = new page();
$request = array();
$request['componentid'] = get_request('componentid','REQUEST');
$request['hash'] = get_request('hash','REQUEST');
$request['password'] = get_request('check_password','REQUEST');
$request['hash'] = get_request('hash','REQUEST',false,'');
$request['password'] = get_request('check_password','REQUEST',false,'');
$request['action'] = get_request('action','REQUEST');
$request['attribute'] = get_request('attr','REQUEST');

View File

@@ -34,7 +34,7 @@ if (get_request('purge','REQUEST')) {
$entry->open();
}
set_cached_item($app['server']->getIndex(),'tree','null',$tree);
set_cached_item($app['server']->getIndex(),$tree,'tree','null');
}
if (get_request('meth','REQUEST') == 'ajax')

View File

@@ -150,7 +150,7 @@ switch($entry['view']) {
foreach ($sattrs as $attr) {
if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$attr->getName())) {
if ((! is_null($entry['value']) && $entry['value']==$attr->getName()) || ! trim($entry['value']))
if (!is_string($entry['value']) || $entry['value']==$attr->getName() || !trim($entry['value']))
$entry['viewed'] = true;
if (isAjaxEnabled() && $entry['value'])
@@ -380,7 +380,7 @@ switch($entry['view']) {
$desc = $rule->getName(false);
if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$rule->getName())) {
if ((! is_null($entry['value']) && $entry['value']==$rule->getName()) || ! trim($entry['value']))
if (!is_string($entry['value']) || $entry['value']==$rule->getName() || !trim($entry['value']))
$entry['viewed'] = true;
if (null != $rule->getDescription())
@@ -468,7 +468,7 @@ switch($entry['view']) {
foreach ($socs as $name => $oclass) {
if (isAjaxEnabled() || (is_null($entry['value']) || ! trim($entry['value']) || $entry['value']==$oclass->getName())) {
if ((! is_null($entry['value']) && $entry['value']==$oclass->getName()) || ! trim($entry['value']))
if (!is_string($entry['value']) || $entry['value']==$oclass->getName() || !trim($entry['value']))
$entry['viewed'] = true;
if (isAjaxEnabled() && $entry['value'])

View File

@@ -31,7 +31,7 @@ foreach ($attrs as $key => $values) {
$sattr = $app['server']->getSchemaAttribute($key);
if ($sattr) {
if ($sattr && $_SESSION[APPCONFIG]->isCommandAvailable('script','schema') && $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link')) {
$href = sprintf('cmd.php?cmd=schema&amp;server_id=%s&amp;view=attributes&amp;viewvalue=%s',$app['server']->getIndex(),$sattr->getName());
printf('<a href="%s" title="%s: %s" >%s</a>',
$href,_('Click to view the schema definition for attribute type'),$sattr->getName(false),$sattr->getName(false));

View File

@@ -40,7 +40,7 @@ switch ($request['location']) {
if (! isset($jpeg_data[$request['attr']][$request['index']])) {
if (function_exists('imagecreate')) {
$im = imagecreate(160,30);
if (is_resource($im)) {
if ($im) {
header('Content-type: image/png');
# Set the background

View File

@@ -133,7 +133,7 @@ class AttributeFactory {
return $this->newGidAttribute($name,$values,$server_id,$source);
} else {
return new Attribute($name,$values,$server_id,$source);
return new PLAAttribute($name,$values,$server_id,$source);
}
}

View File

@@ -12,7 +12,7 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class BinaryAttribute extends Attribute {
class BinaryAttribute extends PLAAttribute {
protected $filepaths;
protected $filenames;

View File

@@ -12,6 +12,6 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class DateAttribute extends Attribute {
class DateAttribute extends PLAAttribute {
}
?>

View File

@@ -12,6 +12,6 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class DnAttribute extends Attribute {
class DnAttribute extends PLAAttribute {
}
?>

View File

@@ -12,6 +12,6 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class GidAttribute extends Attribute {
class GidAttribute extends PLAAttribute {
}
?>

View File

@@ -45,7 +45,8 @@ class HTMLTree extends Tree {
if (! $onlytree) {
$this->draw_menu();
if ($server->getAuthType() != 'config')
if (($server->getAuthType() != 'config') ||
$server->getValue('appearance', 'show_authz'))
$this->draw_logged_in_user();
else
printf('<tr><td class="blank" colspan="%s">&nbsp;</td></tr>',$this->getDepth()+3);
@@ -135,6 +136,7 @@ class HTMLTree extends Tree {
case 'config':
case 'proxy':
case 'sasl':
case 'sasl_external':
break;
default:
@@ -168,7 +170,7 @@ class HTMLTree extends Tree {
if (! is_null($server->inactivityTime())) {
$m = sprintf(_('Inactivity will log you off at %s'),
strftime('%H:%M',$server->inactivityTime()));
date('H:i',$server->inactivityTime()));
printf(' <img width="14" height="14" src="%s/timeout.png" title="%s" alt="%s"/>',IMGDIR,$m,'Timeout');
}
echo '</td></tr>';
@@ -183,10 +185,15 @@ class HTMLTree extends Tree {
$links = '';
$i = 0;
$icons = $_SESSION[APPCONFIG]->getValue('appearance','tree_icons');
if (is_array($_SESSION[APPCONFIG]->getValue('menu','session')))
foreach ($_SESSION[APPCONFIG]->getValue('menu','session') as $link => $title) {
if ($this->get_menu_item($link))
$links .= sprintf('<td class="server_links">%s</td>',$this->get_menu_item($link));
if ($icons && ++$i%$icons == 0)
$links .= '</tr><tr>';
}
# Finally add our logout link.
@@ -328,7 +335,7 @@ class HTMLTree extends Tree {
$server = $this->getServer();
$href = sprintf('cmd.php?cmd=logout&server_id=%s',$server->getIndex());
if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','logout') || in_array($server->getAuthType(),array('config','http','proxy')))
if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','logout') || in_array($server->getAuthType(),array('config','http','proxy','sasl','sasl_external')))
return '';
else
return sprintf('<a href="%s" title="%s"><img src="%s/%s" alt="%s" /><br />%s</a>',
@@ -344,7 +351,7 @@ class HTMLTree extends Tree {
$server = $this->getServer();
$logged_in_dn = $server->getLogin(null);
$logged_in_dn = $server->displayLogin(null);
echo '<tr>';
echo '<td class="spacer"></td>';
printf('<td class="logged_in" colspan="%s">%s: ',$this->getDepth()+3-1,_('Logged in as'));

View File

@@ -12,7 +12,7 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class MultiLineAttribute extends Attribute {
class MultiLineAttribute extends PLAAttribute {
protected $rows = 0;
protected $cols = 0;

View File

@@ -12,6 +12,6 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class ObjectClassAttribute extends Attribute {
class ObjectClassAttribute extends PLAAttribute {
}
?>

View File

@@ -12,7 +12,7 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class Attribute {
class PLAAttribute {
# Attribute Name
public $name;
# Source of this attribute definition
@@ -258,14 +258,14 @@ class Attribute {
}
}
public function getValue($i) {
public function getValue($i, $default=null) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
if (isset($this->values[$i]))
return $this->values[$i];
else
return null;
return $default;
}
public function getOldValue($i) {
@@ -778,7 +778,7 @@ class Attribute {
case 'value':
if (is_array($value))
foreach ($value as $y) {
foreach ($value as $x => $y) {
if (! $this->haveMoreValues()) {
system_message(array(
'title'=>_('Automatically removed attribute values from template'),
@@ -790,7 +790,7 @@ class Attribute {
break;
} else
$this->addValue($y);
$this->addValue($x,$y);
}
else

View File

@@ -97,6 +97,10 @@ class PageRender extends Visitor {
$this->visit('',$attribute);
}
// Sort our attribute values for display, if we are the custom template.
if ($this->template->getID() == 'none')
$this->template->sort();
}
}
@@ -283,7 +287,7 @@ class PageRender extends Visitor {
break;
default:
$vals[$i] = password_hash($passwordvalue,$enc);
$vals[$i] = pla_password_hash($passwordvalue,$enc);
}
$vals = array_unique($vals);
@@ -331,7 +335,17 @@ class PageRender extends Visitor {
if (DEBUGTMP) printf('<font size=-2>%s:<u>%s</u></font><br />',__METHOD__,'Choosing the DEFAULT template, no other template applicable');
# Since getTemplate() returns a default template if the one we want doesnt exist, we can return $templates->getID(), it should be the default.
return $template->getID();
if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template') AND $this->getMode() == 'creation') {
system_message(array(
'title'=>_('No available templates'),
'body'=>_('There are no available active templates for this container.'),
'type'=>'warn'));
return 'invalid';
} else
return $template->getID();
# If there is only 1 defined template, and no default available, then that is our template.
} elseif ((count($templates->getTemplates($this->getMode(),$this->getModeContainer(),true)) == 1) && ! $this->haveDefaultTemplate()) {
@@ -365,7 +379,7 @@ class PageRender extends Visitor {
$href = sprintf('cmd.php?cmd=schema&server_id=%s&view=attributes&viewvalue=%s',
$this->getServerID(),$attribute->getName());
if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link'))
if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema'))
printf('%s',_($attribute->getFriendlyName()));
elseif ($attribute->getLDAPtype())
@@ -524,7 +538,7 @@ class PageRender extends Visitor {
final protected function drawHiddenValueAttribute($attribute,$i) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
printf('<input type="hidden" name="new_values[%s][%s]" id="new_values_%s_%s" value="%s" />',
htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i,
@@ -542,7 +556,7 @@ class PageRender extends Visitor {
final protected function drawOldValueAttribute($attribute,$i) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
echo $attribute->getOldValue($i);
echo htmlspecialchars($attribute->getOldValue($i));
}
/** DRAW DISPLAYED CURRENT VALUES **/
@@ -593,7 +607,7 @@ class PageRender extends Visitor {
protected function drawFormReadOnlyValueAttribute($attribute,$i) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
printf('<input type="text" class="roval" name="new_values[%s][%s]" id="new_values_%s_%s" value="%s" readonly="readonly" />',
htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val));
@@ -602,7 +616,7 @@ class PageRender extends Visitor {
protected function drawFormReadWriteValueAttribute($attribute,$i) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
if ($attribute->getHelper() || $attribute->getVerify())
echo '<table cellspacing="0" cellpadding="0" border="0"><tr><td valign="top">';
@@ -706,7 +720,7 @@ class PageRender extends Visitor {
protected function drawFormReadWriteValueDateAttribute($attribute,$i) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
echo '<span style="white-space: nowrap;">';
printf('<input type="text" class="value" id="new_values_%s_%s" name="new_values[%s][%s]" value="%s" %s%s %s %s/>&nbsp;',
@@ -724,7 +738,7 @@ class PageRender extends Visitor {
protected function drawFormReadWriteValueDnAttribute($attribute,$i) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
if ($attribute->getHelper())
echo '<table cellspacing="0" cellpadding="0"><tr><td valign="top">';
@@ -813,7 +827,7 @@ class PageRender extends Visitor {
if (! $attribute->getOldValue($i))
return;
draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false);
draw_jpeg_photo($this->getServer(),$this->template->getDN(),$i,$attribute->getName(),false,false);
}
/**
@@ -830,16 +844,16 @@ class PageRender extends Visitor {
# If the attribute is modified, the new value needs to be stored in a session variable for the draw_jpeg_photo callback.
if ($attribute->hasBeenModified()) {
$_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i);
draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false);
draw_jpeg_photo(null,$this->template->getDN(),$i,$attribute->getName(),false,false);
} else
draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false);
draw_jpeg_photo($this->getServer(),$this->template->getDN(),$i,$attribute->getName(),false,false);
}
protected function drawFormReadOnlyValueJpegAttribute($attribute,$i) {
$this->draw('HiddenValue',$attribute,$i);
$_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i);
draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false);
draw_jpeg_photo(null,$this->template->getDN(),$i,$attribute->getName(),false,false);
}
protected function drawFormReadOnlyValueMultiLineAttribute($attribute,$i) {
@@ -938,12 +952,12 @@ class PageRender extends Visitor {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$server = $this->getServer();
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
if (trim($val))
$enc_type = get_enc_type($val);
else
$enc_type = $server->getValue('appearance','password_hash');
$enc_type = $server->getValue('appearance','pla_password_hash');
$obfuscate_password = obfuscate_password_display($enc_type);
@@ -960,7 +974,7 @@ class PageRender extends Visitor {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
$server = $this->getServer();
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
$enc_type = get_enc_type($val);
@@ -968,7 +982,7 @@ class PageRender extends Visitor {
if (trim($val))
$enc_type = get_enc_type($val);
else
$enc_type = $server->getValue('appearance','password_hash');
$enc_type = $server->getValue('appearance','pla_password_hash');
echo '<table cellspacing="0" cellpadding="0"><tr><td valign="top">';
@@ -1056,6 +1070,11 @@ class PageRender extends Visitor {
} else {
echo '<table cellspacing="0" cellpadding="0" border="0">';
// For checkbox items, we need to render a blank entry, so that we detect an all-unselect situation
printf('<tr><td colspan="2"><input type="hidden" id="new_values_%s_%s" name="new_values[%s][]" value="%s"/></td></tr>',
htmlspecialchars($attribute->getName()),$j++,
htmlspecialchars($attribute->getName()),'');
foreach ($attribute->getSelection() as $value => $description) {
if (in_array($value,$vals))
$selected[$value] = true;
@@ -1083,7 +1102,7 @@ class PageRender extends Visitor {
# This is a single value attribute
} else {
$val = $attribute->getValue($i) ? $attribute->getValue($i) : $attribute->getDefault();
$val = $attribute->getValue($i) ? $attribute->getValue($i) : (is_null($attribute->getDefault())? '': $attribute->getDefault());
if ($attribute->getHelper())
echo '<table cellspacing="0" cellpadding="0"><tr><td valign="top">';
@@ -1177,7 +1196,8 @@ class PageRender extends Visitor {
else
return false;
return $shadow_date*24*3600;
$shadow_date_seconds = $shadow_date*24*3600;
return ($shadow_date_seconds > PHP_INT_MAX) ? PHP_INT_MAX: $shadow_date_seconds;
}
protected function drawShadowDateShadowAttribute($attribute) {
@@ -1195,15 +1215,15 @@ class PageRender extends Visitor {
echo '<br/><small>';
if (($today < $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_before_today_attrs))
printf('<span style="color:red">(%s)</span>',
strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
date($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
elseif (($today > $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_after_today_attrs))
printf('<span style="color:red">(%s)</span>',
strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
date($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
else
printf('(%s)',
strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
date($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
echo '</small><br />';
}

View File

@@ -12,6 +12,6 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class PasswordAttribute extends Attribute {
class PasswordAttribute extends PLAAttribute {
}
?>

View File

@@ -134,9 +134,9 @@ class Query extends xmlTemplate {
# If this is a custom search, we need to populate are paramters
if ($this->getID() == 'none') {
$bases = get_request('base','REQUEST',false,null);
$query['filter'] = get_request('filter','REQUEST',false,'objectClass=*');
$query['filter'] = get_request('filter','REQUEST',false,'objectClass=*',false);
$query['scope'] = get_request('scope','REQUEST',false,'sub');
$attrs = get_request('display_attrs','REQUEST');
$attrs = get_request('display_attrs','REQUEST',false,'');
$attrs = preg_replace('/\s+/','',$attrs);
if ($attrs)
@@ -247,8 +247,8 @@ class Query extends xmlTemplate {
# If our display order is empty, then dynamically build it
if (! count($result)) {
foreach ($this->results as $details)
foreach ($details as $attrs)
$result = array_merge($result,array_keys(array_change_key_case($attrs)));
foreach ($details as $attrs)
$result = array_merge($result,array_keys(array_change_key_case($attrs)));
$result = array_unique($result);
sort($result);

View File

@@ -229,7 +229,6 @@ class QueryRender extends PageRender {
# If Mass Actions Enabled
if ($_SESSION[APPCONFIG]->getValue('mass','enabled')) {
$mass_actions = array(
'&nbsp;' => '',
_('delete') => 'mass_delete',
_('edit') => 'mass_edit'
);
@@ -281,6 +280,8 @@ class QueryRender extends PageRender {
# Iterate over each attribute for this entry
foreach (explode(',',$ado) as $attr) {
$attr = strtolower($attr);
# Ignore DN, we've already displayed it.
if ($attr == 'dn')
continue;
@@ -320,7 +321,7 @@ class QueryRender extends PageRender {
if (! $results) {
echo _('Search returned no results');
continue;
continue 2;
}
printf('<form action="cmd.php" method="post" id="massform_%s">',$counter);
@@ -406,12 +407,10 @@ class QueryRender extends PageRender {
printf('<tr class="%s">',++$j%2 ? 'odd' : 'even');
printf('<td><input type="checkbox" name="allbox" value="1" onclick="CheckAll(1,\'massform_\',%s);" /></td>',$counter);
printf('<td colspan="%s">',2+count(explode(',',$ado)));
echo '<select name="cmd" onchange="if (this.value) submit();" style="font-size: 12px">';
foreach ($mass_actions as $action => $display)
printf('<option value="%s">%s</option>',$display,$action);
foreach ($mass_actions as $display => $action)
printf('<button type="submit" name="cmd" value="%s">%s</button>&nbsp;&nbsp;',$action,$display);
echo '</select>';
echo '</td>';
echo '</tr>';
}
@@ -462,7 +461,7 @@ class QueryRender extends PageRender {
$results = array();
foreach (explode(',',$this->template->getAttrDisplayOrder()) as $attr)
$results[$attr] = $attribute_factory->newAttribute($attr,array('values'=>array()),$this->getServerID());
$results[strtolower($attr)] = $attribute_factory->newAttribute($attr,array('values'=>array()),$this->getServerID());
return $results;
}
@@ -497,7 +496,7 @@ class QueryRender extends PageRender {
$this->getAjaxRef($base),
$this->getAjaxRef($base),
($show == $this->getAjaxRef($base) ? '#F0F0F0' : '#E0E0E0'),
$base);
htmlspecialchars($base));
}
echo '</tr>';
echo '</table>';
@@ -545,7 +544,7 @@ class QueryRender extends PageRender {
echo ' ]</small>';
echo '<br />';
printf('<small>%s: <b>%s</b></small>',_('Base DN'),$base);
printf('<small>%s: <b>%s</b></small>',_('Base DN'),htmlspecialchars($base));
echo '<br />';
printf('<small>%s: <b>%s</b></small>',_('Filter performed'),htmlspecialchars($this->template->resultsdata[$base]['filter']));

View File

@@ -12,7 +12,7 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class SelectionAttribute extends Attribute {
class SelectionAttribute extends PLAAttribute {
protected $selection = array();
protected $multiple;
protected $default;
@@ -41,7 +41,7 @@ class SelectionAttribute extends Attribute {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
$this->addOption($new_val,$new_val);
$this->addOption($new_val,$i);
}
public function getOptionCount() {

View File

@@ -12,7 +12,7 @@
* @package phpLDAPadmin
* @subpackage Templates
*/
class ShadowAttribute extends Attribute {
class ShadowAttribute extends PLAAttribute {
public $shadow_before_today_attrs = array('shadowLastChange','shadowMin');
public $shadow_after_today_attrs = array('shadowMax','shadowExpire','shadowWarning','shadowInactive');
}

View File

@@ -56,7 +56,7 @@ class Template extends xmlTemplate {
# Template RDN attributes
private $rdn;
public function __construct($server_id,$name=null,$filename=null,$type=null,$id=null) {
public function __construct($server_id,$name='',$filename=null,$type=null,$id=null) {
parent::__construct($server_id,$name,$filename,$type,$id);
# If this is the default template, we might disable leafs by default.
@@ -258,7 +258,7 @@ class Template extends xmlTemplate {
* or delete.
* (OLD values are IGNORED, we will have got them when we build this object from the LDAP server DN.)
*/
public function accept($makeVisible=false) {
public function accept($makeVisible=false,$nocache=false) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -275,7 +275,7 @@ class Template extends xmlTemplate {
$rdnarray = rdn_explode(strtolower(get_rdn(dn_escape($this->dn))));
$counter = 1;
foreach ($server->getDNAttrValues($this->dn,null,LDAP_DEREF_NEVER,array_merge(array('*'),$server->getValue('server','custom_attrs'))) as $attr => $values) {
foreach ($server->getDNAttrValues($this->dn,null,LDAP_DEREF_NEVER,array_merge(array('*'),$server->getValue('server','custom_attrs')),$nocache) as $attr => $values) {
# We ignore DNs.
if ($attr == 'dn')
continue;
@@ -636,10 +636,13 @@ class Template extends xmlTemplate {
public function getDNEncode($url=true) {
// @todo Be nice to do all this in 1 location
$dn = $this->getDN();
if (is_null($dn))
$dn = '';
if ($url)
return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->getDN()));
return urlencode(preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$dn));
else
return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$this->getDN());
return preg_replace('/%([0-9a-fA-F]+)/',"%25\\1",$dn);
}
/**
@@ -1123,10 +1126,11 @@ class Template extends xmlTemplate {
switch ($command) {
/*
autoFill:string
string is a literal string, and may contain many fields like %attr|start-end/flags%
string is a literal string, and may contain many fields like %attr|start-end/flags|additionalcontrolchar%
to substitute values read from other fields.
|start-end is optional, but must be present if the k flag is used.
/flags is optional.
|additionalcontrolchar is optional.
flags may be:
T: Read display text from selection item (drop-down list), otherwise, read the value of the field
@@ -1141,8 +1145,11 @@ class Template extends xmlTemplate {
The string read will be split into fields, using : as a delimiter
"start" indicates which field number to pass through.
K: The string read will be split into fields, using ' ' as a delimiter "start" indicates which field number to pass through.
If additionalcontrolchar is given, it will be used as delimiter (e.g. this allows for splitting e-mail addresses
into domain and domain-local part).
l: Make the result lower case.
U: Make the result upper case.
A: Remap special characters to their corresponding ASCII value
*/
case 'autoFill':
if (! preg_match('/;/',$arg)) {
@@ -1155,8 +1162,8 @@ class Template extends xmlTemplate {
}
list($attr,$string) = preg_split('(([^,]+);(.*))',$arg,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
preg_match_all('/%(\w+)(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%/U',$string,$matchall);
//print"<PRE>";print_r($matchall); //0 = highlevel match, 1 = attr, 2 = subst, 3 = mod
preg_match_all('/%(\w+)(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U',$string,$matchall);
//print"<PRE>";print_r($matchall); //0 = highlevel match, 1 = attr, 2 = subst, 3 = mod, 4 = delimiter
if (! isset($attribute->js['autoFill']))
$attribute->js['autoFill'] = '';
@@ -1183,6 +1190,7 @@ class Template extends xmlTemplate {
$match_attr = strtolower($matchall[1][$index]);
$match_subst = $matchall[2][$index];
$match_mod = $matchall[3][$index];
$match_delim = $matchall[4][$index];
$substrarray = array();
@@ -1220,13 +1228,19 @@ class Template extends xmlTemplate {
$attribute->js['autoFill'] .= sprintf(" %s = %s.split(':')[%s];\n",$match_attr,$match_attr,$tok_idx);
} elseif (strstr($match_mod,'K')) {
preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
if (isset($substrarray[1][0])) {
$tok_idx = $substrarray[1][0];
} else {
$tok_idx = '0';
}
$attribute->js['autoFill'] .= sprintf(" %s = %s.split(' ')[%s];\n",$match_attr,$match_attr,$tok_idx);
preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
if (isset($substrarray[1][0])) {
$tok_idx = $substrarray[1][0];
} else {
$tok_idx = '0';
}
if ($match_delim == '') {
$delimiter = ' ';
} else {
$delimiter = preg_quote($match_delim);
}
$attribute->js['autoFill'] .= sprintf(" %s = %s.split('%s')[%s];\n",$match_attr,$match_attr,$delimiter,$tok_idx);
} else {
preg_match_all('/([0-9]*)-([0-9]*)/',trim($match_subst),$substrarray);
@@ -1251,13 +1265,13 @@ class Template extends xmlTemplate {
# Matchfor only entry without modifiers.
$formula = preg_replace('/^%('.$match_attr.')%$/U','$1 + \'\'',$formula);
# Matchfor only entry with modifiers.
$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%$/U','$1 + \'\'',$formula);
$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%$/U','$1 + \'\'',$formula);
# Matchfor begining entry.
$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%/U','$1 + \'',$formula);
$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U','$1 + \'',$formula);
# Matchfor ending entry.
$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?%$/U','\' + $1 ',$formula);
$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%$/U','\' + $1 ',$formula);
# Match for entries not at begin/end.
$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[:lTUA]+)?%/U','\' + $1 + \'',$formula);
$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U','\' + $1 + \'',$formula);
$attribute->js['autoFill'] .= "\n";
}
@@ -1342,7 +1356,7 @@ class Template extends xmlTemplate {
continue;
if (! $this->isAttrType($objectclassattr,'may'))
$this->setAttrLDAPtype($sattr->getName(false),'optional');
$this->setAttrLDAPtype($sattr->getName(false),'may');
if (! in_array($objectclassattr,$allattrs))
array_push($allattrs,$objectclassattr);
@@ -1563,5 +1577,9 @@ class Template extends xmlTemplate {
public function isNoLeaf() {
return $this->noleaf;
}
public function sort() {
usort($this->attributes,'sortAttrs');
}
}
?>

View File

@@ -48,7 +48,7 @@ class TemplateRender extends PageRender {
$this->page = get_request('page','REQUEST',false,1);
if ($this->template_id) {
if ($this->template_id AND $this->template_id != 'invalid') {
if (! $this->template)
parent::accept();
@@ -59,7 +59,7 @@ class TemplateRender extends PageRender {
$this->layout['action'] = '<td class="icon"><img src="%s/%s" alt="%s" /></td><td><a href="cmd.php?%s" title="%s">%s</a></td>';
$this->layout['actionajax'] = '<td class="icon"><img src="%s/%s" alt="%s" /></td><td><a href="cmd.php?%s" title="%s" onclick="return ajDISPLAY(\'BODY\',\'%s\',\'%s\');">%s</a></td>';
# If we dont want to render this template automatically, we'll return here.
# If we don't want to render this template automatically, we'll return here.
if ($norender)
return;
@@ -139,16 +139,23 @@ class TemplateRender extends PageRender {
return;
}
$function_args = explode(',',$args[0]);
if (function_exists($function))
$vals = call_user_func_array($function,$function_args);
if (!empty($args[0]))
$function_args = explode(',',$args[0]);
else
$function_args = '';
if (function_exists($function)) {
if (empty($function_args))
$vals = call_user_func($function);
else
$vals = call_user_func_array($function,$function_args);
} else {
system_message(array(
'title'=>_('Function doesnt exist'),
'body'=>sprintf('%s (<b>%s</b>)',_('An attempt was made to call a function that doesnt exist'),$function),
'type'=>'warn'));
}
break;
@@ -200,7 +207,7 @@ class TemplateRender extends PageRender {
$next_number = $vals;
foreach ($mod as $calc) {
$operand = $calc{0};
$operand = $calc[0];
$operator = substr ($calc,1);
switch ($operand) {
@@ -264,6 +271,9 @@ class TemplateRender extends PageRender {
*
* * arg 8 (for MultiList)
* - size of displayed list (default: 10 lines)
*
* * arg 9
* - if whether to include parent in sub query TRUE|FALSE
*/
case 'MultiList':
case 'PickList':
@@ -273,7 +283,7 @@ class TemplateRender extends PageRender {
else
$container = $args[5];
# Process filter (arg 1), eventually replace %attr% by it's value set in a previous page.
# Process filter (arg 1), eventually replace %attr% by its value set in a previous page.
preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[1],$filtermatchall);
//print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod
@@ -322,6 +332,9 @@ class TemplateRender extends PageRender {
$vals = array();
foreach ($picklistvalues as $key => $values) {
if (! empty($args[9]) && $container == $key)
continue;
$display = $args[3];
foreach ($matchall[1] as $key => $arg) {
@@ -1679,7 +1692,7 @@ function validateForm(silence) {
// Sometimes the alert gives us enough time!
if (typeof getAttributeComponents != "undefined")
alert("Dont bother, our JS is loaded now!");
alert("Don\'t bother, our JS is loaded now!");
}
validateForm(true);
@@ -2143,7 +2156,7 @@ function fillRec(id,value) {
if ($attribute->isMultiple() && $i > 0)
return;
$val = $attribute->getValue($i);
$val = $attribute->getValue($i, '');
if ($attribute->isVisible()) {
echo '<table cellspacing="0" cellpadding="0" width="100%" border="0"><tr><td class="icon" style="width: 25px;">';
@@ -2371,6 +2384,9 @@ function deleteAttribute(attrName,friendlyName,i)
protected function drawIconObjectClassAttribute($attribute,$val) {
if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema'))
return;
if (strlen($val) > 0) {
$href = sprintf('cmd.php?cmd=schema&server_id=%s&view=objectclasses&viewvalue=%s',
$this->getServerID(),$val);
@@ -2463,7 +2479,7 @@ function deleteAttribute(attrName,friendlyName,i)
if ($val = $attribute->getValue($i))
$default = get_enc_type($val);
else
$default = $this->getServer()->getValue('appearance','password_hash');
$default = $this->getServer()->getValue('appearance','pla_password_hash');
if (! $attribute->getPostValue())
printf('<input type="hidden" name="post_value[%s][]" value="%s" />',$attribute->getName(),$i);

View File

@@ -51,17 +51,24 @@ abstract class Tree {
return null;
$treeclass = $_SESSION[APPCONFIG]->getValue('appearance','tree');
eval('$tree = new '.$treeclass.'($server_id);');
$tree = new $treeclass($server_id);
# If we are not logged in, just return the empty tree.
if (is_null($server->getLogin(null)))
return $tree;
foreach ($server->getBaseDN(null) as $base)
if ($base)
foreach ($server->getBaseDN(null) as $base) {
if ($base) {
$tree->addEntry($base);
set_cached_item($server_id,'tree','null',$tree);
if ($server->getValue('appearance','open_tree')) {
$baseEntry = $tree->getEntry($base);
$baseEntry->open();
}
}
}
set_cached_item($server_id,$tree,'tree','null');
}
return $tree;
@@ -103,7 +110,7 @@ abstract class Tree {
$return = array();
foreach ($this->entries as $details)
if ($details->isBaseDN())
if ($details->isBaseDN() AND ((! $this->getServer()->getValue('server','hide_noaccess_base')) OR $details->isInLdap()))
array_push($return,$details);
return $return;

View File

@@ -22,6 +22,15 @@ abstract class Visitor {
protected $server_id;
public function __call($method,$args) {
# This mapping array allows to map effective class names to
# function name suffixes.
# It has been introduced when class Attribute has been renamed
# to PLAAttribute to avoid a name clash with the built-in
# class of PHP 8.
# Entering a class name mapping here allows to rename the
# class without having to rename the methods too.
static $classmap = array('PLAAttribute' => 'Attribute');
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -33,19 +42,14 @@ abstract class Visitor {
$fnct = array_shift($args);
$object = $args[0];
$class = get_class($object);
$call = "$method$fnct$class";
array_push($methods,$call);
while ($class && ! method_exists($this,$call)) {
for ($class = get_class($object); $class; $class = get_parent_class($class)) {
$call = isset($classmap[$class])? "$method$fnct$classmap[$class]": "$method$fnct$class";
array_push($methods,$call);
if (method_exists($this,$call))
break;
if (defined('DEBUGTMP') && DEBUGTMP)
printf('<font size=-2><i>Class (%s): Method doesnt exist (%s,%s)</i></font><br />',$class,get_class($this),$call);
$class = get_parent_class($class);
$call = "$method$fnct$class";
array_push($methods,$call);
}
if (defined('DEBUGTMP') && DEBUGTMP)
@@ -55,20 +59,7 @@ abstract class Visitor {
printf('<font size=-2>Method Exists: %s::%s (%s)</font><br />',get_class($this),$call,$args);
if (method_exists($this,$call)) {
$call .= '(';
for ($i = 0; $i < count($args); $i++)
if ($i == 0)
$call .= sprintf('$args[%s]',$i);
else
$call .= sprintf(',$args[%s]',$i);
$call .= ');';
if (defined('DEBUGTMP') && DEBUGTMP)
printf('<font size=-2><b>Invoking Method: $this->%s</b></font><br />',$call);
eval('$r = $this->'.$call);
$r = call_user_func_array(array($this,$call),$args);
if (isset($r))
return $r;

View File

@@ -315,7 +315,7 @@ class Horde_Cipher_blowfish {
$keyLen = count($key);
for ($i = 0; $i < $iMax; $i++) {
for ($t = 0; $t < 4; $t++) {
$keyXor = ($keyXor << 8) | (($key[$keyPos]) & 0x0ff);
$keyXor = (($keyXor << 8) | (($key[$keyPos]) & 0x0ff)) & 0xFFFFFFFF;
if (++$keyPos == $keyLen) {
$keyPos = 0;
}
@@ -389,6 +389,37 @@ class Horde_Cipher_blowfish {
return pack("NN", $parts['L'], $parts['R']);
}
/**
* Perform an encryption/decryption step.
*
* @param Int $x The bits source for the S tables indexing.
*
* @return Int The 32-bit step result.
*/
function _cryptStep($x)
{
if (PHP_INT_SIZE > 4)
return ((($this->s1[($x >> 24) & 0xFF] + $this->s2[($x >> 16) & 0xFF]) ^ $this->s3[($x >> 8) & 0xFF]) + $this->s4[$x & 0xFF]) & 0xFFFF;
/* For 32-bit machines, split values into 16-bit high and low parts
to avoid negative values and 32-bit overflows. */
$a = $this->s1[($x >> 24) & 0xFF];
$b = $this->s2[($x >> 16) & 0xFF];
$h = (($a >> 16) & 0xFFFF) + (($b >> 16) & 0xFFFF);
$l = ($a & 0xFFFF) + ($b & 0xFFFF);
if ($l & ~0xFFFF)
$h++;
$a = $this->s3[($x >> 8) & 0xFF];
$h ^= $a >> 16;
$l ^= $a;
$a = $this->s4[$x & 0xFF];
$h = ($h & 0xFFFF) + (($a >> 16) & 0xFFFF);
$l = ($l & 0xFFFF) + ($a & 0xFFFF);
if ($l & ~0xFFFF)
$h++;
return (($h & 0xFFFF) << 16) | ($l & 0xFFFF);
}
/**
* Encrypt a block on data.
*
@@ -400,22 +431,22 @@ class Horde_Cipher_blowfish {
function _encryptBlock($L, $R)
{
$L ^= $this->p[0];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[1];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[2];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[3];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[4];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[5];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[6];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[7];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[8];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[9];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[10];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[11];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[12];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[13];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[14];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[15];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[16];
$R ^= $this->_cryptStep($L) ^ $this->p[1];
$L ^= $this->_cryptStep($R) ^ $this->p[2];
$R ^= $this->_cryptStep($L) ^ $this->p[3];
$L ^= $this->_cryptStep($R) ^ $this->p[4];
$R ^= $this->_cryptStep($L) ^ $this->p[5];
$L ^= $this->_cryptStep($R) ^ $this->p[6];
$R ^= $this->_cryptStep($L) ^ $this->p[7];
$L ^= $this->_cryptStep($R) ^ $this->p[8];
$R ^= $this->_cryptStep($L) ^ $this->p[9];
$L ^= $this->_cryptStep($R) ^ $this->p[10];
$R ^= $this->_cryptStep($L) ^ $this->p[11];
$L ^= $this->_cryptStep($R) ^ $this->p[12];
$R ^= $this->_cryptStep($L) ^ $this->p[13];
$L ^= $this->_cryptStep($R) ^ $this->p[14];
$R ^= $this->_cryptStep($L) ^ $this->p[15];
$L ^= $this->_cryptStep($R) ^ $this->p[16];
$R ^= $this->p[17];
return array('L' => $R, 'R' => $L);
@@ -445,23 +476,22 @@ class Horde_Cipher_blowfish {
list($L, $R) = array_values($unpack);
$L ^= $this->p[17];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[15];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[14];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[13];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[12];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[11];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[10];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[9];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[8];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[7];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[6];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[5];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[4];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[3];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[2];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[1];
$R ^= $this->_cryptStep($L) ^ $this->p[16];
$L ^= $this->_cryptStep($R) ^ $this->p[15];
$R ^= $this->_cryptStep($L) ^ $this->p[14];
$L ^= $this->_cryptStep($R) ^ $this->p[13];
$R ^= $this->_cryptStep($L) ^ $this->p[12];
$L ^= $this->_cryptStep($R) ^ $this->p[11];
$R ^= $this->_cryptStep($L) ^ $this->p[10];
$L ^= $this->_cryptStep($R) ^ $this->p[9];
$R ^= $this->_cryptStep($L) ^ $this->p[8];
$L ^= $this->_cryptStep($R) ^ $this->p[7];
$R ^= $this->_cryptStep($L) ^ $this->p[6];
$L ^= $this->_cryptStep($R) ^ $this->p[5];
$R ^= $this->_cryptStep($L) ^ $this->p[4];
$L ^= $this->_cryptStep($R) ^ $this->p[3];
$R ^= $this->_cryptStep($L) ^ $this->p[2];
$L ^= $this->_cryptStep($R) ^ $this->p[1];
$decrypted = pack("NN", $R ^ $this->p[0], $L);
return $decrypted;
}

View File

@@ -259,15 +259,16 @@ if ($app['language'] == 'auto') {
if ((substr($lang,0,2) == 'en') ||
(file_exists($app['language_dir']) && is_readable($app['language_dir']))) {
# Set language
putenv('LANG='.$lang); # e.g. LANG=de_DE
$lang .= '.UTF-8';
setlocale(LC_ALL,$lang); # set LC_ALL to de_DE
bindtextdomain('messages',LANGDIR);
bind_textdomain_codeset('messages','UTF-8');
textdomain('messages');
header('Content-type: text/html; charset=UTF-8',true);
if (extension_loaded('gettext')) {
# Set language
putenv('LANG='.$lang); # e.g. LANG=de_DE
$lang .= '.UTF-8';
setlocale(LC_ALL,$lang); # set LC_ALL to de_DE
bindtextdomain('messages',LANGDIR);
bind_textdomain_codeset('messages','UTF-8');
textdomain('messages');
header('Content-type: text/html; charset=UTF-8',true);
}
break;
}
}
@@ -296,7 +297,9 @@ if ($app['language'] == 'auto') {
* Strip slashes from GET, POST, and COOKIE variables if this
* PHP install is configured to automatically addslashes()
*/
if (@get_magic_quotes_gpc() && (! isset($slashes_stripped) || ! $slashes_stripped)) {
if (@version_compare(phpversion(), '5.4.0', '<') &&
@get_magic_quotes_gpc() &&
(!isset($slashes_stripped) || !$slashes_stripped)) {
array_stripslashes($_REQUEST);
array_stripslashes($_GET);
array_stripslashes($_POST);

View File

@@ -8,7 +8,7 @@
*/
/** The minimum version of PHP required to run phpLDAPadmin. */
define('REQUIRED_PHP_VERSION','5.0.0');
define('REQUIRED_PHP_VERSION','7.0.0');
/**
* The config class contains all our configuration settings for a session.
@@ -261,6 +261,15 @@ class Config {
'desc'=>'LDAP search filter for the tree entries',
'default'=>'(objectClass=*)');
$this->default->appearance['tree_icons'] = array(
'desc'=>'Number of Tree Icons to display on a row',
'default'=>0);
# PLA will not display the header and footer parts in minimal mode.
$this->default->appearance['minimalMode'] = array(
'desc'=>'Minimal mode hides header and footer parts',
'default'=>false);
## Caching
$this->default->cache['schema'] = array(
'desc'=>'Cache Schema Activity',
@@ -439,7 +448,7 @@ class Config {
*/
$this->default->modify_member['groupattr'] = array(
'desc'=>'Group member attributes',
'default'=>array('member','uniqueMember','memberUid'));
'default'=>array('member','uniqueMember','memberUid','uid'));
/**
* Attribute that is added to the group member attribute. For groupOfNames or groupOfUniqueNames this is dn,
@@ -495,7 +504,7 @@ class Config {
$this->default->session['memorylimit'] = array(
'desc'=>'Set the PHP memorylimit warning threshold.',
'default'=>24);
'default'=>'24M');
$this->default->session['timelimit'] = array(
'desc'=>'Set the PHP timelimit.',
@@ -545,6 +554,32 @@ class Config {
'desc'=>'Disable random salt for crypt()',
'default'=>false);
$this->default->password['available_types'] = array(
'desc'=>'List of available password types used for encryption',
'default'=>array(
''=>'clear',
'bcrypt'=>'bcrypt',
'blowfish'=>'blowfish',
'crypt'=>'crypt',
'ext_des'=>'ext_des',
'md5'=>'md5',
'k5key'=>'k5key',
'md5crypt'=>'md5crypt',
'sha'=>'sha',
'smd5'=>'smd5',
'ssha'=>'ssha',
'sha256'=>'sha256',
'ssha256'=>'ssha256',
'sha384'=>'sha384',
'ssha384'=>'ssha384',
'sha512'=>'sha512',
'ssha512'=>'ssha512',
'sha256crypt'=>'sha256crypt',
'sha512crypt'=>'sha512crypt',
'argon2i'=>'argon2i',
'argon2id'=>'argon2id',
));
/** Search display
* By default, when searching you may display a list or a table of results.
* Set this to 'table' to see table formatted results.
@@ -569,6 +604,20 @@ class Config {
$this->default->search['time_limit'] = array(
'desc'=>'Maximum time to allow unlimited size_limit searches to the ldap server',
'default'=>120);
/* reCAPTCHA Login */
$this->default->session['reCAPTCHA-enable'] = array(
'desc'=>'Status reCAPTCHA (true | false)',
'default'=>false);
$this->default->session['reCAPTCHA-key-site'] = array(
'desc'=>'Site Key',
'default'=>"<put-here-key-site>");
$this->default->session['reCAPTCHA-key-server'] = array(
'desc'=>'Server key',
'default'=>"<put-here-key-server>");
}
/**

View File

@@ -139,6 +139,7 @@ abstract class DS {
case 'proxy':
case 'session':
case 'sasl':
case 'sasl_external':
return $this->getValue('login','auth_type');
default:
@@ -194,6 +195,8 @@ abstract class DS {
else
return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']);
case 'sasl_external':
return 'external';
default:
die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType()));
}
@@ -215,6 +218,7 @@ abstract class DS {
return true;
case 'config':
case 'sasl_external':
return true;
case 'proxy':
@@ -274,6 +278,8 @@ abstract class DS {
else
return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']);
case 'sasl_external':
return '';
default:
die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType()));
}
@@ -368,11 +374,11 @@ abstract class DS {
$userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']);
$CACHE[$this->index][$method] = $this->login($userDN, '', $method);
}
# Otherwise, use the user name as is
else {
$CACHE[$this->index][$method] = $this->login($_SERVER['REMOTE_USER'], '', $method);
}
# For GSSAPI Authentication + mod_auth_kerb and Basic Authentication
} else
$CACHE[$this->index][$method] = $this->login(isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '', '', $method);
break;
@@ -400,6 +406,7 @@ abstract class DS {
set_cookie($method.'-PASS','',time()-3600,'/');
case 'config':
case 'sasl_external':
return true;
case 'http':
@@ -430,7 +437,8 @@ abstract class DS {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
if (! trim($this->getLogin(null)) && $_SESSION[APPCONFIG]->getValue('appearance','anonymous_bind_implies_read_only'))
$login = $this->getLogin(null);
if (!($login && trim($login)) && $_SESSION[APPCONFIG]->getValue('appearance','anonymous_bind_implies_read_only'))
return true;
else
return $this->getValue('server','read_only');
@@ -542,6 +550,10 @@ class Datastore {
'desc'=>'Whether this server is visible',
'default'=>true);
$this->default->server['hide_noaccess_base'] = array(
'desc'=>'If base DNs are not accessible, hide them instead of showing create',
'default'=>false);
# Authentication Information
$this->default->login['auth_type'] = array(
'desc'=>'Authentication Type',
@@ -570,6 +582,10 @@ class Datastore {
'desc'=>'User Login ID to bind to this DS',
'default'=>null);
$this->default->login['bind_dn_template'] = array(
'desc'=>'Template string for user login DN to bind to this DS. Use \'%s\' where user input should be inserted.',
'default'=>null);
$this->default->login['bind_pass'] = array(
'desc'=>'User Login Password to bind to this DS',
'default'=>null);

View File

@@ -19,8 +19,6 @@ class ldap extends DS {
private $_schema_entries = null;
# Schema DN
private $_schemaDN = null;
# Attributes that should be treated as MAY attributes, even though the scheme has them as MUST attributes.
private $force_may = array();
public function __construct($index) {
if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
@@ -56,6 +54,22 @@ class ldap extends DS {
'desc'=>'Connect using TLS',
'default'=>false);
$this->default->server['tls_cacert'] = array(
'desc'=>'TLS Certificate Authority',
'default'=>null);
$this->default->server['tls_cacertdir'] = array(
'desc'=>'TLS Certificate Authority Directory',
'default'=>null);
$this->default->server['tls_cert'] = array(
'desc'=>'TLS Client Certificate',
'default'=>null);
$this->default->server['tls_key'] = array(
'desc'=>'TLS Client Certificate Key',
'default'=>null);
# Login Details
$this->default->login['attr'] = array(
'desc'=>'Attribute to use to find the users DN',
@@ -82,14 +96,9 @@ class ldap extends DS {
'default'=>array());
# SASL configuration
$this->default->server['sasl'] = array(
'desc'=>'Use SASL authentication when binding LDAP server',
'default'=>false);
$this->default->sasl['mech'] = array(
'desc'=>'SASL mechanism used while binding LDAP server',
'untested'=>true,
'default'=>'PLAIN');
'default'=>'GSSAPI');
$this->default->sasl['realm'] = array(
'desc'=>'SASL realm name',
@@ -117,6 +126,35 @@ class ldap extends DS {
'default'=>null);
}
/**
* Set LDAP option with error checking...
*
* @param resource Connection resource
* @param string Name of option to set
* @param mixed Option value
* @return boolean false if error
*/
private function setLdapOption($resource, $option, $value) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',16,0,__FILE__,__LINE__,__METHOD__,$fargs);
if (! defined($option)) {
system_message(array(
'title'=>sprintf('%s',_('Undefined LDAP option')),
'body'=>sprintf('<b>%s</b>: %s <b>%s</b>',_('Error'),_('Required LDAP option not defined'),$option),
'type'=>'error'));
return false;
}
if (! @ldap_set_option($resource,constant($option),$value)) {
system_message(array(
'title'=>sprintf('%s',_('Failed to set LDAP option')),
'body'=>sprintf('<b>%s</b>: %s <b>%s</b>',_('Error'),_('Failed to set LDAP option'),$option),
'type'=>'error'));
return false;
}
return true;
}
/**
* Required ABSTRACT functions
*/
@@ -171,30 +209,45 @@ class ldap extends DS {
else
$resource = ldap_connect($this->getValue('server','host'));
$this->noconnect = false;
$CACHE[$this->index][$method] = $resource;
if (DEBUG_ENABLED)
debug_log('LDAP Resource [%s], Host [%s], Port [%s]',16,0,__FILE__,__LINE__,__METHOD__,
$resource,$this->getValue('server','host'),$this->getValue('server','port'));
if (! is_resource($resource))
if (!$resource)
debug_dump_backtrace('UNHANDLED, $resource is not a resource',1);
# Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
ldap_set_option($resource,LDAP_OPT_PROTOCOL_VERSION,3);
if (! $this->setLdapOption($resource,'LDAP_OPT_PROTOCOL_VERSION',3))
$this->noconnect = true;
/* Disabling this makes it possible to browse the tree for Active Directory, and seems
* to not affect other LDAP servers (tested with OpenLDAP) as phpLDAPadmin explicitly
* specifies deref behavior for each ldap_search operation. */
ldap_set_option($resource,LDAP_OPT_REFERRALS,0);
elseif (! $this->setLdapOption($resource,'LDAP_OPT_REFERRALS',0))
$this->noconnect = true;
/* Enabling manageDsaIt to be able to browse through glued entries
* 2.16.840.1.113730.3.4.2 : "ManageDsaIT Control" "RFC 3296" "The client may provide
* the ManageDsaIT control with an operation to indicate that the operation is intended
* to manage objects within the DSA (server) Information Tree. The control causes
* Directory-specific entries (DSEs), regardless of type, to be treated as normal entries
* allowing clients to interrogate and update these entries using LDAP operations." */
elseif (! $this->setLdapOption($resource,'LDAP_OPT_SERVER_CONTROLS',array(array('oid'=>'2.16.840.1.113730.3.4.2'))))
$this->noconnect = true;
# Try to fire up TLS is specified in the config
if ($this->isTLSEnabled())
$this->startTLS($resource);
if ($this->isTLSEnabled() && !$this->noconnect)
if(! $this->startTLS($resource))
$this->noconnect = true;
# If SASL has been configured for binding, then start it now.
if ($this->isSASLEnabled())
$bind['result'] = $this->startSASL($resource,$method);
if ($this->noconnect)
$bind['result'] = false;
elseif ($this->isSASLEnabled())
$bind['result'] = $this->startSASL($resource,$method,$bind['id'],$bind['pass']);
# Normal bind...
else
@@ -210,17 +263,16 @@ class ldap extends DS {
if (DEBUG_ENABLED)
debug_log('Leaving with FALSE, bind FAILed',16,0,__FILE__,__LINE__,__METHOD__);
$this->noconnect = true;
system_message(array(
'title'=>sprintf('%s %s',_('Unable to connect to LDAP server'),$this->getName()),
'body'=>sprintf('<b>%s</b>: %s (%s) for <b>%s</b>',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
'type'=>'error'));
if (! $this->noconnect) {
$this->noconnect = true;
system_message(array(
'title'=>sprintf('%s %s',_('Unable to connect to LDAP server'),$this->getName()),
'body'=>sprintf('<b>%s</b>: %s (%s) for <b>%s</b>',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
'type'=>'error'));
}
$CACHE[$this->index][$method] = null;
} else {
$this->noconnect = false;
# If this is a proxy session, we need to switch to the proxy user
if ($this->isProxyEnabled() && $bind['id'] && $method != 'anon')
@@ -254,11 +306,11 @@ class ldap extends DS {
if (! is_null($user)) {
# If login,attr is set to DN, then user should be a DN
if (($this->getValue('login','attr') == 'dn') || $method != 'user')
$userDN = $user;
$userDN = $this->getValue('login', 'bind_dn_template') ? $this->fillDNTemplate($user) : $user;
else
$userDN = $this->getLoginID($user,'login');
if (! $userDN && $this->getValue('login','fallback_dn'))
if (! $userDN && $this->getValue('login','fallback_dn') && strpos($user, '='))
$userDN = $user;
if (! $userDN)
@@ -285,7 +337,7 @@ class ldap extends DS {
$connect = $this->connect($method,false,$new);
# If we didnt log in...
if (! is_resource($connect) || $this->noconnect || ! $this->userIsAllowedLogin($userDN)) {
if (!$connect || $this->noconnect || ! $this->userIsAllowedLogin($userDN)) {
$this->logout($method);
return false;
@@ -358,22 +410,24 @@ class ldap extends DS {
if ($debug)
debug_dump(array('query'=>$query,'server'=>$this->getIndex(),'con'=>$this->connect($method)));
$search = null;
$resource = $this->connect($method,$debug);
switch ($query['scope']) {
case 'base':
$search = @ldap_read($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
break;
if ($resource)
switch ($query['scope']) {
case 'base':
$search = @ldap_read($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
break;
case 'one':
$search = @ldap_list($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
break;
case 'one':
$search = @ldap_list($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
break;
case 'sub':
default:
$search = @ldap_search($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
break;
}
case 'sub':
default:
$search = @ldap_search($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
break;
}
if ($debug)
debug_dump(array('method'=>$method,'search'=>$search,'error'=>$this->getErrorMessage()));
@@ -511,6 +565,15 @@ class ldap extends DS {
return $this->getBaseDN();
}
private function fillDNTemplate($user) {
foreach($this->getLoginBaseDN() as $base)
if(substr_compare($user, $base, -strlen($base)) === 0)
return $user; // $user already passed as DN
// fill template
return sprintf($this->getValue('login', 'bind_dn_template'), preg_replace('/([,\\\\#+<>;"=])/', '\\\\$1', $user));
}
/**
* Return the login classes that a user must have to login
*/
@@ -560,10 +623,41 @@ class ldap extends DS {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
if (! $this->getValue('server','tls') || (function_exists('ldap_start_tls') && ! @ldap_start_tls($resource))) {
// LDAP_OPT_X_TLS_ options must be set globally ($res = null)
// until LDAP_OPT_X_TLS_NEWCTX is exported,
// NOTE: new values will require php-fpm or other stateful
// php servers to be restarted, and are global for all php
// users in the process pool!
$val = $this->getValue('server','tls_cacert');
if (! empty($val))
if (! $this->setLdapOption(null, 'LDAP_OPT_X_TLS_CACERTFILE', $val))
return false;
$val = $this->getValue('server','tls_cacertdir');
if (! empty($val))
if (! $this->setLdapOption(null, 'LDAP_OPT_X_TLS_CACERTDIR', $val))
return false;
$val = $this->getValue('server','tls_cert');
if (! empty($val))
if (! $this->setLdapOption(null, 'LDAP_OPT_X_TLS_CERTFILE', $val))
return false;
$val = $this->getValue('server','tls_key');
if (! empty($val))
if (! $this->setLdapOption(null, 'LDAP_OPT_X_TLS_KEYFILE', $val))
return false;
if (! @ldap_start_tls($resource)) {
$diag_error='';
ldap_get_option($resource, LDAP_OPT_DIAGNOSTIC_MESSAGE, $diag_error);
if (! empty($diag_error)) {
$diag_error = '<br>'.$diag_error;
}
$error = ldap_error($resource);
system_message(array(
'title'=>sprintf('%s (%s)',_('Could not start TLS.'),$this->getName()),
'body'=>sprintf('<b>%s</b>: %s',_('Error'),_('Could not start TLS. Please check your LDAP server configuration.')),
'body'=>sprintf('<b>%s</b>: %s %s%s',_('Error'),_('Could not start TLS.'),$error,$diag_error),
'type'=>'error'));
return false;
@@ -577,7 +671,11 @@ class ldap extends DS {
*
* Users may configure phpLDAPadmin to use SASL in config,php thus:
* <code>
* $servers->setValue('server','sasl',true|false);
* $servers->setValue('login','auth_type','sasl');
* OR
* $servers->setValue('sasl','mech','PLAIN');
* OR
* $servers->setValue('login','auth_type','sasl_external');
* </code>
*
* @return boolean
@@ -586,12 +684,20 @@ class ldap extends DS {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
if ($this->getValue('server','sasl') && ! function_exists('ldap_sasl_bind')) {
error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
return false;
if (! in_array($this->getValue('login','auth_type'), array('sasl','sasl_external'))) {
// check if SASL mech uses login from other auth_types
if (! in_array(strtolower($this->getValue('sasl', 'mech')), array('plain')))
return false;
}
} else
return $this->getValue('server','sasl');
if (! function_exists('ldap_sasl_bind')) {
error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
return false;
}
# If we get here, SASL must be configured.
return true;
}
/**
@@ -600,54 +706,78 @@ class ldap extends DS {
*
* @todo This has not been tested, please let the developers know if this function works as expected.
*/
private function startSASL($resource,$method) {
private function startSASL($resource,$method,$login,$pass) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
static $CACHE = array();
if (! $this->getValue('server','sasl') || ! function_exists('ldap_start_tls'))
# We shouldnt be doing SASL binds for anonymous queries?
if ($method == 'anon')
return false;
if (! isset($CACHE['login_dn'])) {
$CACHE['login_dn'] = is_null($this->getLogin($method)) ? $this->getLogin('user') : $this->getLogin($method);
$CACHE['login_pass'] = is_null($this->getPassword($method)) ? $this->getPassword('user') : $this->getPassword($method);
# EXTERNAL mech is really a different authType
if ($this->getAuthType() == 'sasl_external') {
return @ldap_sasl_bind($resource,NULL,NULL,
'EXTERNAL',NULL,NULL,
$this->getValue('sasl','props'));
}
$mech = strtolower($this->getValue('sasl','mech'));
# At the moment, we have only implemented GSSAPI and PLAIN
if (! in_array(strtolower($this->getValue('sasl','mech')),array('gssapi','plain'))) {
system_message(array(
'title'=>_('SASL Method not implemented'),
'body'=>sprintf('<b>%s</b>: %s %s',_('Error'),$this->getValue('sasl','mech'),_('has not been implemented yet')),
'type'=>'error'));
return false;
}
if (strtolower($this->getValue('sasl','mech')) == 'plain') {
return @ldap_sasl_bind($resource,NULL,$pass,'PLAIN',
$this->getValue('sasl','realm'),
$login,
$this->getValue('sasl','props'));
}
if (! isset($CACHE['login_dn']))
$CACHE['login_dn'] = $login;
$CACHE['authz_id'] = '';
/*
# Do we need to rewrite authz_id?
if (! isset($CACHE['authz_id']))
if (! trim($this->getValue('sasl','authz_id')) && $mech != 'gssapi') {
if (! trim($this->getValue('sasl','authz_id')) && strtolower($this->getValue('sasl','mech')) != 'gssapi') {
if (DEBUG_ENABLED)
debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,
$CACHE['login_dn'],
$this->getValue('sasl','authz_id_regex'),
$this->getValue('sasl','authz_id_replacement'));
if (DEBUG_ENABLED)
debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,
$CACHE['login_dn'],
$this->getValue('sasl','authz_id_regex'),
$this->getValue('sasl','authz_id_replacement'));
$CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'),
$this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']);
$CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'),
$this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']);
# Invalid regex?
if (is_null($CACHE['authz_id']))
error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'),
$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')),
'error','index.php');
# Invalid regex?
if (is_null($CACHE['authz_id']))
error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'),
$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')),
'error','index.php');
if (DEBUG_ENABLED)
debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
$resource,
$this->getValue('sasl','mech'),
$this->getValue('sasl','realm'),
$CACHE['authz_id'],
$this->getValue('sasl','props'));
if (DEBUG_ENABLED)
debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
$resource,
$this->getValue('sasl','mech'),
$this->getValue('sasl','realm'),
$CACHE['authz_id'],
$this->getValue('sasl','props'));
} else
$CACHE['authz_id'] = $this->getValue('sasl','authz_id');
*/
# @todo this function is different in PHP5.1 and PHP5.2
return @ldap_sasl_bind($resource,$CACHE['login_dn'],$CACHE['login_pass'],
return @ldap_sasl_bind($resource,NULL,'',
$this->getValue('sasl','mech'),
$this->getValue('sasl','realm'),
$CACHE['authz_id'],
@@ -746,7 +876,7 @@ class ldap extends DS {
'value'=>sprintf('dn:%s',$dn),
'iscritical' => true);
if (! ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array($ctrl))) {
if (! @ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array($ctrl))) {
system_message(array(
'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
'body'=>sprintf('<b>%s</b>: %s (%s) for <b>%s</b>',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
@@ -902,7 +1032,7 @@ class ldap extends DS {
$dn = $this->getContainer($dn);
if ($dn == $top)
break;
continue;
} elseif($value)
$dn = sprintf('%s,%s',$value,$dn);
@@ -1108,13 +1238,14 @@ class ldap extends DS {
if (is_array($dn)) {
$a = array();
foreach ($dn as $key => $rdn)
$a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn);
foreach ($dn as $key => $rdn) {
$a[$key] = preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function($m) { return chr(hexdec($m[1])); }, $rdn);
}
return $a;
} else
return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn);
} else {
return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function($m) { return chr(hexdec($m[1])); }, $dn);
}
}
public function getRootDSE($method=null) {
@@ -1159,7 +1290,7 @@ class ldap extends DS {
$search = @ldap_read($this->connect($method),$dn,'objectclass=*',array('subschemaSubentry'),false,0,10,LDAP_DEREF_NEVER);
if (DEBUG_ENABLED)
debug_log('Search returned (%s)',24,0,__FILE__,__LINE__,__METHOD__,is_resource($search));
debug_log('Search returned (%s)',24,0,__FILE__,__LINE__,__METHOD__,!!$search);
# Fix for broken ldap.conf configuration.
if (! $search && ! $dn) {
@@ -1172,7 +1303,7 @@ class ldap extends DS {
if (DEBUG_ENABLED)
debug_log('Search returned (%s) for base (%s)',24,0,__FILE__,__LINE__,__METHOD__,
is_resource($search),$base);
!!$search,$base);
if ($search)
break;
@@ -1367,6 +1498,40 @@ class ldap extends DS {
}
}
# Option 3: try cn=config
$olc_schema = 'olc'.$schema_to_fetch;
$olc_schema_found = false;
if (is_null($schema_search)) {
if (DEBUG_ENABLED)
debug_log('Attempting cn=config work-around...',24,0,__FILE__,__LINE__,__METHOD__);
$ldap_dn = 'cn=schema,cn=config';
$ldap_filter = '(objectClass=*)';
$schema_search = @ldap_search($this->connect($method),$ldap_dn,$ldap_filter,array($olc_schema),false,0,10,LDAP_DEREF_NEVER);
if (! is_null($schema_search)) {
$schema_entries = @ldap_get_entries($this->connect($method),$schema_search);
if (DEBUG_ENABLED)
debug_log('Search returned [%s]',24,0,__FILE__,__LINE__,__METHOD__,$schema_entries);
if ($schema_entries) {
if (DEBUG_ENABLED)
debug_log('Found schema with filter of (%s) and attribute filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter,$olc_schema);
$olc_schema_found = true;
} else {
if (DEBUG_ENABLED)
debug_log('Didnt find schema with filter (%s) and attribute filter (%s)',24,0,__FILE__,__LINE__,__METHOD__,$ldap_filter,$olc_schema);
unset($schema_entries);
$schema_search = null;
}
}
}
if (is_null($schema_search)) {
/* Still cant find the schema, try with the RootDSE
* Attempt to pull schema from Root DSE with scope "base", or
@@ -1436,9 +1601,35 @@ class ldap extends DS {
return $return;
}
if(! isset($schema_entries[0][$schema_to_fetch])) {
if ($olc_schema_found) {
unset ($schema_entries['count']);
foreach ($schema_entries as $entry) {
if (isset($entry[$olc_schema])) {
unset($entry[$olc_schema]['count']);
foreach ($entry[$olc_schema] as $schema_definition)
/* Schema definitions in child nodes prefix the schema entries with "{n}"
the preg_replace call strips out this prefix. */
$schema[] = preg_replace('/^\{\d*\}\(/','(',$schema_definition);
}
}
if (isset($schema)) {
$this->_schema_entries[$olc_schema] = $schema;
if (DEBUG_ENABLED)
debug_log('Returning (%s)',25,0,__FILE__,__LINE__,__METHOD__,$schema);
return $schema;
} else
return null;
}
if (! isset($schema_entries[0][$schema_to_fetch])) {
if (in_array($schema_to_fetch,$schema_error_message_array)) {
error(sprintf('Our attempts to find your SCHEMA for "%s" has return UNEXPECTED results.<br /><br /><small>(We expected a "%s" in the $schema array but it wasnt there.)</small><br /><br />%s<br /><br />Dump of $schema_search:<hr /><pre><small>%s</small></pre>',
error(sprintf('Our attempts to find your SCHEMA for "%s" have return UNEXPECTED results.<br /><br /><small>(We expected a "%s" in the $schema array but it wasnt there.)</small><br /><br />%s<br /><br />Dump of $schema_search:<hr /><pre><small>%s</small></pre>',
$schema_to_fetch,gettype($schema_search),$schema_error_message,serialize($schema_entries)),'error','index.php');
} else {
@@ -1579,7 +1770,7 @@ class ldap extends DS {
ksort($return);
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item($this->index,'schema','objectclasses',$return);
set_cached_item($this->index,$return,'schema','objectclasses');
}
if (DEBUG_ENABLED)
@@ -1764,7 +1955,7 @@ class ldap extends DS {
$return = $attrs;
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item($this->index,'schema','attributes',$return);
set_cached_item($this->index,$return,'schema','attributes');
}
if (DEBUG_ENABLED)
@@ -1840,7 +2031,7 @@ class ldap extends DS {
$return = $rules;
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item($this->index,'schema','matchingrules',$return);
set_cached_item($this->index,$return,'schema','matchingrules');
}
if (DEBUG_ENABLED)
@@ -1889,7 +2080,7 @@ class ldap extends DS {
ksort($return);
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item($this->index,'schema','syntaxes',$return);
set_cached_item($this->index,$return,'schema','syntaxes');
}
if (DEBUG_ENABLED)
@@ -1902,14 +2093,13 @@ class ldap extends DS {
* This function determines if the specified attribute is contained in the force_may list
* as configured in config.php.
*
* @return boolean True if the specified attribute is in the $force_may list and false
* otherwise.
* @return boolean True if the specified attribute is configured to be force as a may attribute
*/
function isForceMay($attr_name) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
return in_array($attr_name,$this->force_may);
return in_array($attr_name,unserialize(strtolower(serialize($this->getValue('server','force_may')))));
}
/**
@@ -1994,7 +2184,7 @@ class ldap extends DS {
* @see getDNSysAttrs
* @see getDNAttrValue
*/
public function getDNAttrValues($dn,$method=null,$deref=LDAP_DEREF_NEVER,$attrs=array('*','+')) {
public function getDNAttrValues($dn,$method=null,$deref=LDAP_DEREF_NEVER,$attrs=array('*','+'),$nocache=false) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -2010,7 +2200,7 @@ class ldap extends DS {
elseif (in_array('*',$attrs))
$cacheindex = '*';
if (! is_null($cacheindex) && isset($CACHE[$this->index][$method][$dn][$cacheindex])) {
if (! $nocache && ! is_null($cacheindex) && isset($CACHE[$this->index][$method][$dn][$cacheindex])) {
$results = $CACHE[$this->index][$method][$dn][$cacheindex];
if (DEBUG_ENABLED)
@@ -2128,7 +2318,7 @@ class ldap extends DS {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
$type = ($sattr = $this->getSchemaAttribute($attr_name)) ? $sattr->getType() : null;
$type = ($sattr = $this->getSchemaAttribute($attr_name)) ? $sattr->getType() : '';
if (! strcasecmp('boolean',$type) ||
! strcasecmp('isCriticalSystemObject',$attr_name) ||
@@ -2193,8 +2383,8 @@ class ldap extends DS {
/* Strangely, some attributeTypes may not show up in the server
* schema. This behavior has been observed in MS Active Directory.*/
$type = null;
$syntax = null;
$type = '';
$syntax = '';
} else {
$type = $sattr->getType();
@@ -2210,6 +2400,8 @@ class ldap extends DS {
strcasecmp($attr_name,'objectSID') == 0 ||
strcasecmp($attr_name,'auditingPolicy') == 0 ||
strcasecmp($attr_name,'jpegPhoto') == 0 ||
strcasecmp($attr_name,'krbExtraData') == 0 ||
strcasecmp($attr_name,'krbPrincipalKey') == 0 ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.10' ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.28' ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.5' ||

View File

@@ -13,13 +13,10 @@
* @subpackage DataStore
*/
class ldap_pla extends ldap {
# Attributes that should be treated as MAY attributes, even though the scheme has them as MUST attributes.
private $force_may = array();
function __construct($index) {
parent::__construct($index);
$this->default->appearance['password_hash'] = array(
$this->default->appearance['pla_password_hash'] = array(
'desc'=>'Default HASH to use for passwords',
'default'=>'md5');
@@ -27,6 +24,14 @@ class ldap_pla extends ldap {
'desc'=>'Whether to show the "Create new Entry here" in the tree browser',
'default'=>true);
$this->default->appearance['open_tree'] = array(
'desc'=>'Whether to initially open each tree',
'default'=>false);
$this->default->appearance['show_authz'] = array(
'desc'=>'Enable display of authorization ID as login',
'default'=>false);
$this->default->login['fallback_dn'] = array(
'desc'=>'If the attribute base login fails, see if a DN was entered',
'default'=>false);
@@ -89,6 +94,11 @@ class ldap_pla extends ldap {
'*'
));
$this->default->server['force_may'] = array(
'desc'=>'Force server MUST attributes as MAY attributes',
'default'=>array(
));
# Settings for auto_number
$this->default->auto_number['enable'] = array(
'desc'=>'Enable the AUTO UID feature',
@@ -361,7 +371,7 @@ class ldap_pla extends ldap {
$tree->addEntry($dn);
set_cached_item($this->index,'tree','null',$tree);
set_cached_item($this->index,$tree,'tree','null');
run_hook('post_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array));
@@ -393,7 +403,7 @@ class ldap_pla extends ldap {
$tree = get_cached_item($this->index,'tree');
$tree->delEntry($dn);
set_cached_item($this->index,'tree','null',$tree);
set_cached_item($this->index,$tree,'tree','null');
run_hook('post_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn));
}
@@ -420,7 +430,7 @@ class ldap_pla extends ldap {
$newdn = sprintf('%s,%s',$new_rdn,$container);
$tree->renameEntry($dn,$newdn);
set_cached_item($this->index,'tree','null',$tree);
set_cached_item($this->index,$tree,'tree','null');
run_hook('post_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container));
}
@@ -589,10 +599,16 @@ class ldap_pla extends ldap {
# Build our search filter to double check each attribute.
$query['filter'] = '(|';
foreach ($checkattrs as $attr)
foreach ($checkattrs as $attr) {
if (!is_array($attrs[$attr])) {
$val = $attrs[$attr];
$query['filter'] .= sprintf('(%s=%s)',$attr,$val);
continue;
}
foreach ($attrs[$attr] as $val)
if ($val)
$query['filter'] .= sprintf('(%s=%s)',$attr,$val);
}
$query['filter'] .= ')';
$query['attrs'] = $checkattrs;
@@ -649,5 +665,23 @@ class ldap_pla extends ldap {
$_SESSION['ACTIVITY'][$this->getIndex()] = $this->inactivityTime();
return true;
}
/**
* Return login, or authorization ID if show_authz enabled
*/
public function displayLogin($method=null) {
// check for whoami function, added in 7.2
if ($this->getValue('appearance', 'show_authz') && function_exists('ldap_exop_whoami')) {
$result = @ldap_exop_whoami($this->connect($method));
if ($result) // strip any dn: or u: prefix
$result = preg_replace('/^(u|dn):/i', '', $result);
else // fall back to login on error
$result = $this->getLogin($method);
return $result;
}
else {
return $this->getLogin($method);
}
}
}
?>

View File

@@ -125,7 +125,7 @@ abstract class Export {
$query = array();
$base = get_request('dn','REQUEST');
$query['baseok'] = true;
$query['filter'] = get_request('filter','REQUEST',false,'objectclass=*');
$query['filter'] = get_request('filter','REQUEST',false,'objectclass=*',false);
$query['scope'] = get_request('scope','REQUEST',false,'base');
$query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','export');
$query['size_limit'] = 0;
@@ -223,7 +223,7 @@ abstract class Export {
*/
protected function isSafeAscii($str) {
for ($i=0;$i<strlen($str);$i++)
if (ord($str{$i}) < 32 || ord($str{$i}) > 127)
if (ord($str[$i]) < 32 || ord($str[$i]) > 127)
return false;
return true;
@@ -324,9 +324,9 @@ class ExportCSV extends Export {
}
if ($this->compress)
echo gzencode($output);
return gzencode($output);
else
echo $output;
return $output;
}
/**
@@ -428,9 +428,9 @@ class ExportDSML extends Export {
$output .= sprintf('</dsml>%s',$this->br);
if ($this->compress)
echo gzencode($output);
return gzencode($output);
else
echo $output;
return $output;
}
}
@@ -506,9 +506,9 @@ class ExportLDIF extends Export {
}
if ($this->compress)
echo gzencode($output);
return gzencode($output);
else
echo $output;
return $output;
}
/**
@@ -578,6 +578,7 @@ class ExportVCARD extends Export {
*/
function export() {
$server = $this->getServer();
$output = '';
# Sift through the entries.
foreach ($this->results as $base => $results) {
@@ -591,10 +592,11 @@ class ExportVCARD extends Export {
$addr .= $dndetails[$attr];
unset($dndetails[$attr]);
}
$addr .= ';';
}
$output = sprintf('BEGIN:VCARD%s',$this->br);
$output .= sprintf('BEGIN:VCARD%s',$this->br);
# Loop for the attributes
foreach ($dndetails as $key => $attr) {
@@ -633,9 +635,9 @@ class ExportVCARD extends Export {
}
if ($this->compress)
echo gzencode($output);
return gzencode($output);
else
echo $output;
return $output;
}
}
?>

View File

@@ -21,6 +21,7 @@ define('TMPLDIR',sprintf('%s/',realpath(LIBDIR.'../templates/')));
define('DOCDIR',sprintf('%s/',realpath(LIBDIR.'../doc/')));
define('HOOKSDIR',sprintf('%s/',realpath(LIBDIR.'../hooks/')));
define('JSDIR','js/');
define('SESSION_CIPHER','aes-256-gcm');
/**
* Supplimental functions
@@ -51,7 +52,7 @@ if (file_exists(LIBDIR.'functions.custom.php'))
/**
* Loads class definition
*/
function __autoload($className) {
function pla_autoload($className) {
if (file_exists(HOOKSDIR."classes/$className.php"))
require_once(HOOKSDIR."classes/$className.php");
elseif (file_exists(LIBDIR."$className.php"))
@@ -66,10 +67,16 @@ function __autoload($className) {
'type'=>'error'));
}
if (version_compare(phpversion(), '7.0', '>=')) {
spl_autoload_register('pla_autoload');
} else {
eval('function __autoload($className) {pla_autoload($className);}');
}
/**
* Strips all slashes from the specified array in place (pass by ref).
* @param Array The array to strip slashes from, typically one of
* $_GET, $_POST, or $_COOKIE.
* $_GET, $_POST, or $_COOKIE.
*/
function array_stripslashes(&$array) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
@@ -124,12 +131,13 @@ function app_error_handler($errno,$errstr,$file,$lineno) {
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
/**
* error_reporting will be 0 if the error context occurred
* within a function call with '@' preprended (ie, @ldap_bind() );
* error_reporting will be only the non-ignorable error number bits
* if the error context occurred within a function call with '@'
* preprended (ie, @ldap_bind() );
* So, don't report errors if the caller has specifically
* disabled them with '@'
*/
if (ini_get('error_reporting') == 0 || error_reporting() == 0)
if (!(ini_get('error_reporting') & error_reporting() & $errno))
return;
$file = basename($file);
@@ -325,16 +333,38 @@ function check_config($config_file) {
$config->setServers($servers);
# Check the memory limit parameter.
if ((ini_get('memory_limit') > -1) && ini_get('memory_limit') < $config->getValue('session','memorylimit'))
system_message(array(
'title'=>_('Memory Limit low.'),
'body'=>sprintf('Your php memory limit is low - currently %s, you should increase it to atleast %s. This is normally controlled in /etc/php.ini.',
ini_get('memory_limit'),$config->getValue('session','memorylimit')),
'type'=>'error'));
$limit = memory_str_to_int(ini_get('memory_limit'));
if ($limit != -1) {
$threshold = memory_str_to_int($config->getValue('session','memorylimit'));
if ($limit < $threshold) {
system_message(array(
'title' => _('Memory Limit low.'),
'body' => sprintf('Your php memory limit is low - currently %s (%s), you should increase it to atleast %s (%s). This is normally controlled in /etc/php.ini.',
ini_get('memory_limit'), $limit, $config->getValue('session','memorylimit'), $threshold),
'type'=>'error'
));
}
}
return $config;
}
/**
* Converts shorthand memory notation string to an integer that represents the
* given amount in bytes (ie. "128M" -> 134217728).
*
* @param string|int $value
* @return int
*/
function memory_str_to_int($value) {
$value = trim(strtolower($value));
if (intval($value) > 0 && preg_match('/^(\d+)([kmg])?$/', $value, $match, PREG_UNMATCHED_AS_NULL)) {
[$int, $mod] = [intval($match[1]), $match[2]];
$pow = [NULL => 0, 'k' => 1, 'm' => 2, 'g' => 3][$mod];
return $int * 1024 ** $pow;
}
return intval($value);
}
/**
* Commands available in the control_panel of the page
*
@@ -362,7 +392,7 @@ function cmd_control_pane($type) {
'hide_debug_info'=>array(
'title'=>_('Show Cache'),
'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('script','show_cache') : false,
'enable'=>isset($_SESSION[APPCONFIG]) ? ($_SESSION[APPCONFIG]->isCommandAvailable('script','show_cache')) && (! $_SESSION[APPCONFIG]->getValue('appearance','hide_debug_info')) : false,
'link'=>sprintf('href="cmd.php?cmd=show_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=show_cache\',\'%s\');" title="%s"',
_('Loading'),_('Show Cache'),_('Show Cache')),
'image'=>sprintf('<img src="%s/debug-cache.png" alt="%s" />',IMGDIR,_('Show Cache'))),
@@ -645,14 +675,14 @@ function error($msg,$type='note',$redirect=null,$fatal=false,$backtrace=false) {
*
* @return The form GET/REQUEST/SESSION/POST variable value or its default
*/
function get_request($attr,$type='POST',$die=false,$default=null) {
function get_request($attr,$type='POST',$die=false,$default=null,$preventXSS=true) {
switch($type) {
case 'GET':
$value = isset($_GET[$attr]) ? (is_array($_GET[$attr]) ? $_GET[$attr] : (trim(empty($_GET['nodecode'][$attr]) ? rawurldecode($_GET[$attr]) : $_GET[$attr]))) : $default;
$value = isset($_GET[$attr]) ? (is_array($_GET[$attr]) ? $_GET[$attr] : (empty($_GET['nodecode'][$attr]) ? rawurldecode($_GET[$attr]) : $_GET[$attr])) : $default;
break;
case 'REQUEST':
$value = isset($_REQUEST[$attr]) ? (is_array($_REQUEST[$attr]) ? $_REQUEST[$attr] : trim(empty($_REQUEST['nodecode'][$attr]) ? rawurldecode($_REQUEST[$attr]) : $_REQUEST[$attr])) : $default;
$value = isset($_REQUEST[$attr]) ? (is_array($_REQUEST[$attr]) ? $_REQUEST[$attr] : (empty($_REQUEST['nodecode'][$attr]) ? rawurldecode($_REQUEST[$attr]) : $_REQUEST[$attr])) : $default;
break;
case 'SESSION':
@@ -661,22 +691,39 @@ function get_request($attr,$type='POST',$die=false,$default=null) {
case 'POST':
default:
$value = isset($_POST[$attr]) ? (is_array($_POST[$attr]) ? $_POST[$attr] : trim(empty($_POST['nodecode'][$attr]) ? rawurldecode($_POST[$attr]) : $_POST[$attr])) : $default;
$value = isset($_POST[$attr]) ? (is_array($_POST[$attr]) ? $_POST[$attr] : (empty($_POST['nodecode'][$attr]) ? rawurldecode($_POST[$attr]) : $_POST[$attr])) : $default;
break;
}
if ($die && is_null($value))
system_message(array(
'title'=>_('Generic Error'),
'body'=>sprintf('%s: Called "%s" without "%s" using "%s"',
basename($_SERVER['PHP_SELF']),get_request('cmd','REQUEST'),$attr,$type),
basename($_SERVER['PHP_SELF']),get_request('cmd','REQUEST'),preventXSS($attr),preventXSS($type)),
'type'=>'error'),
'index.php');
if($preventXSS && !is_null($value))
$value = preventXSS($value);
return $value;
}
/**
* Prevent XSS function. This function can usage has preventXSS(get_request('cmd','REQUEST'))
* Return valor escape XSS.
*/
function preventXSS($data){
if (gettype($data) == 'array') {
foreach ($data as $key => $value) {
if (gettype($value) == 'array')
$data[$key] = preventXSS($value);
else
$data[$key] = htmlspecialchars($value);
}
return $data;
}
return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
}
/*
* Record a system message.
* This function can be used as an alternative to generate a system message, if page hasnt yet been defined.
*/
@@ -745,7 +792,14 @@ function blowfish_encrypt($data,$secret=null) {
if (! trim($secret))
return $data;
if (function_exists('mcrypt_module_open')) {
if (! empty($data) && function_exists('openssl_encrypt') && in_array(SESSION_CIPHER, openssl_get_cipher_methods())) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(SESSION_CIPHER));
$keylen = openssl_cipher_iv_length(SESSION_CIPHER) * 2;
$encrypted = openssl_encrypt($data, SESSION_CIPHER, substr($secret,0,$keylen), $options=0, $iv, $tag);
return base64_encode($encrypted . '::' . $iv . '::' . $tag);
}
if (function_exists('mcrypt_module_open') && ! empty($data)) {
$td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,'');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM);
mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv);
@@ -771,6 +825,7 @@ function blowfish_encrypt($data,$secret=null) {
$encrypt .= $pma_cipher->encryptBlock($block, $secret);
}
return base64_encode($encrypt);
}
@@ -800,7 +855,13 @@ function blowfish_decrypt($encdata,$secret=null) {
if (! trim($secret))
return $encdata;
if (function_exists('mcrypt_module_open')) {
if (! empty($encdata) && function_exists('openssl_encrypt') && in_array(SESSION_CIPHER, openssl_get_cipher_methods())) {
$keylen = openssl_cipher_iv_length(SESSION_CIPHER) * 2;
list($encryptedData, $iv, $tag) = explode('::', base64_decode($encdata), 3);
return trim(openssl_decrypt($encryptedData, SESSION_CIPHER, substr($secret,0,$keylen), $options=0, $iv, $tag));
}
if (function_exists('mcrypt_module_open') && ! empty($encdata)) {
$td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,'');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM);
mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv);
@@ -822,7 +883,8 @@ function blowfish_decrypt($encdata,$secret=null) {
for ($i=0; $i<strlen($data); $i+=8)
$decrypt .= $pma_cipher->decryptBlock(substr($data, $i, 8), $secret);
$return = trim($decrypt);
// Strip off our \0's that were added.
$return = preg_replace("/\\0*$/",'',$decrypt);
$CACHE[$encdata] = $return;
return $return;
}
@@ -893,7 +955,7 @@ function get_cached_item($index,$item,$subitem='null') {
*
* Returns true on success of false on failure.
*/
function set_cached_item($index,$item,$subitem='null',$data) {
function set_cached_item($index,$data,$item,$subitem='null') {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -991,6 +1053,23 @@ function get_custom_file($index,$filename,$path) {
return $return;
}
/**
* Replacement for create_function() which is deprecated as of php 7.2
*
* @param string The function arguments
* @param string The function code
*/
function pla_create_function($args, $code) {
if (version_compare(phpversion(),'7.0','>=')) {
# anonymous functions were introduced in PHP 5.3.0
return eval("return function(".$args."){".$code."};");
} else {
# create_function is deprecated in php 7.2
return create_function($args, $code);
}
}
/**
* Sort a multi dimensional array.
*
@@ -1003,8 +1082,9 @@ function masort(&$data,$sortby,$rev=0) {
if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
# if the array to sort is null or empty
if (! $data) return;
# if the array to sort is null or empty, or if we have some nasty chars
if (! preg_match('/^[a-zA-Z0-9_]+(\([a-zA-Z0-9_,]*\))?$/',$sortby) || ! $data)
return;
static $CACHE = array();
@@ -1077,7 +1157,7 @@ function masort(&$data,$sortby,$rev=0) {
$code .= 'return $c;';
$CACHE[$sortby] = create_function('$a, $b',$code);
$CACHE[$sortby] = pla_create_function('$a, $b',$code);
}
uasort($data,$CACHE[$sortby]);
@@ -1216,6 +1296,9 @@ function is_mail_string($str) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
if (is_null($str))
return false;
$mail_regex = "/^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$/";
if (preg_match($mail_regex,$str))
@@ -1234,6 +1317,9 @@ function is_url_string($str) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
if (is_null($str))
return false;
$url_regex = '/^(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/';
if (preg_match($url_regex,$str))
@@ -1245,29 +1331,29 @@ function is_url_string($str) {
/**
* Compares 2 DNs. If they are equivelant, returns 0, otherwise,
* returns their sorting order (similar to strcmp()):
* Returns < 0 if dn1 is less than dn2.
* Returns > 0 if dn1 is greater than dn2.
* Returns < 0 if dn1 is less than dn2.
* Returns > 0 if dn1 is greater than dn2.
*
* The comparison is performed starting with the top-most element
* of the DN. Thus, the following list:
* <code>
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* dc=example,dc=com
* cn=Fred,ou=people,dc=example,dc=org
* cn=Dave,ou=people,dc=example,dc=org
* </code>
* <code>
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* dc=example,dc=com
* cn=Fred,ou=people,dc=example,dc=org
* cn=Dave,ou=people,dc=example,dc=org
* </code>
* Will be sorted thus using usort( $list, "pla_compare_dns" ):
* <code>
* dc=com
* dc=example,dc=com
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* cn=Dave,ou=people,dc=example,dc=org
* cn=Fred,ou=people,dc=example,dc=org
* </code>
* <code>
* dc=com
* dc=example,dc=com
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* cn=Dave,ou=people,dc=example,dc=org
* cn=Fred,ou=people,dc=example,dc=org
* </code>
*
* @param string The first of two DNs to compare
* @param string The second of two DNs to compare
@@ -1468,10 +1554,10 @@ function get_next_number($base,$attr,$increment=false,$filter=false,$startmin=nu
for ($i=0;$i<count($autonum);$i++) {
$num = $autonum[$i] < $minNumber ? $minNumber : $autonum[$i];
/* If we're at the end of the list, or we've found a gap between this number and the
following, use the next available number in the gap. */
if ($i+1 == count($autonum) || $autonum[$i+1] > $num+1)
return $autonum[$i] >= $num ? $num+1 : $num;
/* If we're at the end of the list, or we've found a gap between this number and the
following, use the next available number in the gap. */
if ($i+1 == count($autonum) || $autonum[$i+1] > $num+1)
return $autonum[$i] >= $num ? $num+1 : $num;
}
# If we didnt find a suitable gap and are all above the minNumber, we'll just return the $minNumber
@@ -1585,7 +1671,7 @@ function get_icon($server_id,$dn,$object_classes=array()) {
# Return icon filename based upon objectClass value
if (in_array('sambaaccount',$object_classes) &&
'$' == $rdn{ strlen($rdn) - 1 })
'$' == $rdn[ strlen($rdn) - 1 ])
return 'nt_machine.png';
if (in_array('sambaaccount',$object_classes))
@@ -1621,6 +1707,9 @@ function get_icon($server_id,$dn,$object_classes=array()) {
elseif (in_array('room',$object_classes))
return 'door.png';
elseif (in_array('iphost',$object_classes))
return 'host.png';
elseif (in_array('device',$object_classes))
return 'device.png';
@@ -1658,9 +1747,6 @@ function get_icon($server_id,$dn,$object_classes=array()) {
elseif (in_array('groupofuniquenames',$object_classes))
return 'ldap-uniquegroup.png';
elseif (in_array('iphost',$object_classes))
return 'host.png';
elseif (in_array('nlsproductcontainer',$object_classes))
return 'n.png';
@@ -1775,15 +1861,9 @@ function random_salt($length) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
$possible = '0123456789'.
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'./';
$str = '';
mt_srand((double)microtime() * 1000000);
while (strlen($str) < $length)
$str .= substr($possible,(rand()%strlen($possible)),1);
$str = bin2hex(random_bytes(ceil($length/2)));
if ($length % 2 == 1)
return substr($str, 0, -1);
return $str;
}
@@ -1985,8 +2065,8 @@ function ldap_error_msg($msg,$errnum) {
*
* Usage Examples:
* <code>
* draw_jpeg_photo(0,'cn=Bob,ou=People,dc=example,dc=com',"jpegPhoto",0,true,array('img_opts'=>"border: 1px; width: 150px"));
* draw_jpeg_photo(1,'cn=Fred,ou=People,dc=example,dc=com',null,1);
* draw_jpeg_photo(0,'cn=Bob,ou=People,dc=example,dc=com',0,"jpegPhoto",true,array('img_opts'=>"border: 1px; width: 150px"));
* draw_jpeg_photo(1,'cn=Fred,ou=People,dc=example,dc=com',1,null);
* </code>
*
* @param object The Server to get the image from.
@@ -1999,7 +2079,7 @@ function ldap_error_msg($msg,$errnum) {
* @param array Specifies optional image and CSS style attributes for the table tag. Supported keys are
* fixed_width, fixed_height, img_opts.
*/
function draw_jpeg_photo($server,$dn,$attr_name='jpegphoto',$index,$draw_delete_buttons=false,$options=array()) {
function draw_jpeg_photo($server,$dn,$index,$attr_name='jpegphoto',$draw_delete_buttons=false,$options=array()) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -2101,18 +2181,7 @@ function password_types() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
return array(
''=>'clear',
'blowfish'=>'blowfish',
'crypt'=>'crypt',
'ext_des'=>'ext_des',
'md5'=>'md5',
'k5key'=>'k5key',
'md5crypt'=>'md5crypt',
'sha'=>'sha',
'smd5'=>'smd5',
'ssha'=>'ssha'
);
return $_SESSION[APPCONFIG]->getValue('password', 'available_types');
}
/**
@@ -2120,10 +2189,11 @@ function password_types() {
*
* @param string The password to hash in clear text.
* @param string Standard LDAP encryption type which must be one of
* crypt, ext_des, md5crypt, blowfish, md5, sha, smd5, ssha, or clear.
* crypt, ext_des, md5crypt, blowfish, md5, sha, smd5, ssha, sha512,
* sha256crypt, sha512crypt, or clear.
* @return string The hashed password.
*/
function password_hash($password_clear,$enc_type) {
function pla_password_hash($password_clear,$enc_type) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -2167,7 +2237,7 @@ function password_hash($password_clear,$enc_type) {
break;
case 'md5':
$new_value = sprintf('{MD5}%s',base64_encode(pack('H*',md5($password_clear))));
$new_value = sprintf('{MD5}%s',base64_encode(md5($password_clear, true)));
break;
case 'md5crypt':
@@ -2179,37 +2249,93 @@ function password_hash($password_clear,$enc_type) {
break;
case 'sha':
# Use php 4.3.0+ sha1 function, if it is available.
if (function_exists('sha1'))
$new_value = sprintf('{SHA}%s',base64_encode(pack('H*',sha1($password_clear))));
elseif (function_exists('mhash'))
$new_value = sprintf('{SHA}%s',base64_encode(mhash(MHASH_SHA1,$password_clear)));
else
error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php');
$new_value = sprintf('{SHA}%s',base64_encode(sha1($password_clear, true)));
break;
case 'ssha':
if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) {
mt_srand((double)microtime()*1000000);
$salt = mhash_keygen_s2k(MHASH_SHA1,$password_clear,substr(pack('h*',md5(mt_rand())),0,8),4);
$new_value = sprintf('{SSHA}%s',base64_encode(mhash(MHASH_SHA1,$password_clear.$salt).$salt));
} else {
error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php');
}
$salt = hex2bin(random_salt(8));
$new_value = sprintf('{SSHA}%s',base64_encode(sha1($password_clear.$salt, true).$salt));
break;
case 'smd5':
if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) {
mt_srand((double)microtime()*1000000);
$salt = mhash_keygen_s2k(MHASH_MD5,$password_clear,substr(pack('h*',md5(mt_rand())),0,8),4);
$new_value = sprintf('{SMD5}%s',base64_encode(mhash(MHASH_MD5,$password_clear.$salt).$salt));
case 'bcrypt':
$options = [
'cost' => 8,
];
#Checking if password_hash() function is available.
if (function_exists('password_hash'))
$new_value = sprintf('{BCRYPT}%s',base64_encode(password_hash($password_clear, PASSWORD_BCRYPT, $options)));
else
error(_('Your PHP install does not have the password_hash() function. Cannot do BCRYPT hashes.'),'error','index.php');
} else {
error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php');
}
break;
case 'smd5':
$salt = hex2bin(random_salt(8));
$new_value = sprintf('{SMD5}%s',base64_encode(md5($password_clear.$salt, true).$salt));
break;
case 'sha256':
$new_value = sprintf('{SHA256}%s', base64_encode(hash('sha256', $password_clear, true)));
break;
case 'ssha256':
$salt = hex2bin(random_salt(8));
$new_value = sprintf('{SSHA256}%s', base64_encode(hash('sha256', $password_clear.$salt, true).$salt));
break;
case 'sha384':
$new_value = sprintf('{SHA384}%s', base64_encode(hash('sha384', $password_clear, true)));
break;
case 'ssha384':
$salt = hex2bin(random_salt(8));
$new_value = sprintf('{SSHA384}%s', base64_encode(hash('sha384', $password_clear.$salt, true).$salt));
break;
case 'sha512':
$new_value = sprintf('{SHA512}%s', base64_encode(hash('sha512', $password_clear, true)));
break;
case 'ssha512':
$salt = hex2bin(random_salt(8));
$new_value = sprintf('{SSHA512}%s', base64_encode(hash('sha512', $password_clear.$salt, true).$salt));
break;
case 'sha256crypt':
if (! defined('CRYPT_SHA256') || CRYPT_SHA256 == 0)
error(_('Your system crypt library does not support sha256crypt encryption.'),'error','index.php');
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$5$'.random_salt(8)));
break;
case 'sha512crypt':
if (! defined('CRYPT_SHA512') || CRYPT_SHA512 == 0)
error(_('Your system crypt library does not support sha512crypt encryption.'),'error','index.php');
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$6$'.random_salt(8)));
break;
case 'argon2i':
if (! defined('PASSWORD_ARGON2I'))
error(_('Your system does not support argon2i encryption (PHP 7.2 or upper is required).'),'error','index.php');
$new_value = sprintf('{ARGON2}%s',password_hash($password_clear,PASSWORD_ARGON2I));
break;
case 'argon2id':
if (! defined('PASSWORD_ARGON2ID'))
error(_('Your system does not support argon2id encryption (PHP 7.3 or upper is required).'),'error','index.php');
$new_value = sprintf('{ARGON2}%s',password_hash($password_clear,PASSWORD_ARGON2ID));
break;
@@ -2230,6 +2356,7 @@ function password_hash($password_clear,$enc_type) {
* @return Boolean True if the clear password matches the hash, and false otherwise.
*/
function password_check($cryptedpassword,$plainpassword,$attribute='userpassword') {
$plainpassword = htmlspecialchars_decode($plainpassword);
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -2238,13 +2365,13 @@ function password_check($cryptedpassword,$plainpassword,$attribute='userpassword
switch($attribute) {
case 'sambalmpassword':
if (strcmp($smb->lmhash($plainpassword),$cryptedpassword) == 0)
if (strcmp($smb->lmhash($plainpassword),strtoupper($cryptedpassword)) == 0)
return true;
else
return false;
case 'sambantpassword':
if (strcmp($smb->nthash($plainpassword),$cryptedpassword) == 0)
if (strcmp($smb->nthash($plainpassword),strtoupper($cryptedpassword)) == 0)
return true;
else
return false;
@@ -2264,47 +2391,52 @@ function password_check($cryptedpassword,$plainpassword,$attribute='userpassword
switch($cypher) {
# SSHA crypted passwords
case 'ssha':
# Check php mhash support before using it
if (function_exists('mhash')) {
$hash = base64_decode($cryptedpassword);
$hash = base64_decode($cryptedpassword);
# OpenLDAP uses a 4 byte salt, SunDS uses an 8 byte salt - both from char 20.
$salt = substr($hash,20);
$new_hash = base64_encode(mhash(MHASH_SHA1,$plainpassword.$salt).$salt);
# OpenLDAP uses a 4 byte salt, SunDS uses an 8 byte salt - both from char 20.
$salt = substr($hash,20);
$new_hash = base64_encode(sha1($plainpassword.$salt, true).$salt);
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
} else {
error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php');
}
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
break;
#BCRYPT hashed passwords
case 'bcrypt':
# Check php password_verify support before using it
if (function_exists('password_verify')) {
$hash = base64_decode($cryptedpassword);
if (password_verify($plainpassword, $hash)) {
return true;
} else {
return false;
}
} else {
error(_('Your PHP install does not have the password_verify() function. Cannot do Bcrypt hashes.'),'error','index.php');
}
break;
# Salted MD5
case 'smd5':
# Check php mhash support before using it
if (function_exists('mhash')) {
$hash = base64_decode($cryptedpassword);
$salt = substr($hash,16);
$new_hash = base64_encode(mhash(MHASH_MD5,$plainpassword.$salt).$salt);
$hash = base64_decode($cryptedpassword);
$salt = substr($hash,16);
$new_hash = base64_encode(md5($plainpassword.$salt).$salt, true);
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
} else {
error(_('Your PHP install does not have the mhash() function. Cannot do SHA hashes.'),'error','index.php');
}
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
break;
# SHA crypted passwords
case 'sha':
if (strcasecmp(password_hash($plainpassword,'sha'),'{SHA}'.$cryptedpassword) == 0)
if (strcasecmp(pla_password_hash($plainpassword,'sha'),'{SHA}'.$cryptedpassword) == 0)
return true;
else
return false;
@@ -2313,7 +2445,7 @@ function password_check($cryptedpassword,$plainpassword,$attribute='userpassword
# MD5 crypted passwords
case 'md5':
if( strcasecmp(password_hash($plainpassword,'md5'),'{MD5}'.$cryptedpassword) == 0)
if( strcasecmp(pla_password_hash($plainpassword,'md5'),'{MD5}'.$cryptedpassword) == 0)
return true;
else
return false;
@@ -2376,6 +2508,80 @@ function password_check($cryptedpassword,$plainpassword,$attribute='userpassword
break;
# SHA256 crypted passwords
case 'sha256':
if (strcasecmp(pla_password_hash($plainpassword,'sha256'),'{SHA256}'.$cryptedpassword) == 0)
return true;
else
return false;
break;
# Salted SHA256 crypted passwords
case 'ssha256':
$hash = base64_decode($cryptedpassword);
$salt = substr($hash,64);
$new_hash = base64_encode(hash('sha256', $plainpassword.$salt, true).$salt);
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
break;
# SHA384 crypted passwords
case 'sha384':
if (strcasecmp(pla_password_hash($plainpassword,'sha384'),'{SHA384}'.$cryptedpassword) == 0)
return true;
else
return false;
break;
# Salted SHA384 crypted passwords
case 'ssha384':
$hash = base64_decode($cryptedpassword);
$salt = substr($hash,64);
$new_hash = base64_encode(hash('sha384', $plainpassword.$salt, true).$salt);
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
break;
# SHA512 crypted passwords
case 'sha512':
if (strcasecmp(pla_password_hash($plainpassword,'sha512'),'{SHA512}'.$cryptedpassword) == 0)
return true;
else
return false;
break;
# Salted SHA512 crypted passwords
case 'ssha512':
$hash = base64_decode($cryptedpassword);
$salt = substr($hash,64);
$new_hash = base64_encode(hash('sha512', $plainpassword.$salt, true).$salt);
if (strcmp($cryptedpassword,$new_hash) == 0)
return true;
else
return false;
break;
# Argon2 crypted passwords
case 'argon2':
if (password_verify($plainpassword, $cryptedpassword))
return true;
else
return false;
break;
# No crypt is given assume plaintext passwords are used
default:
if ($plainpassword == $cryptedpassword)
@@ -2419,6 +2625,16 @@ function get_enc_type($user_password) {
elseif (preg_match('/{[^}]+}_+/',$user_password))
$enc_type = 'ext_des';
}
elseif (strcasecmp($enc_type,'argon2') == 0) {
if (preg_match('/{ARGON2}\$argon2i\$/',$user_password))
$enc_type = 'argon2i';
elseif (preg_match('/{ARGON2}\$argon2id\$/',$user_password))
$enc_type = 'argon2id';
}
return $enc_type;
@@ -2447,6 +2663,32 @@ function draw_chooser_link($form,$element,$include_choose_text=true,$rdn='none')
printf('<span class="x-small"><a href="%s" title="%s">%s</a></span>',$href,$title,_('browse'));
}
/**
* http://php.net/manual/en/function.ldap-explode-dn.php#34724
* fixed for:
* Keep attention on UTF8 encoded DNs. Since openLDAP >=2.1.2
* ldap_explode_dn turns unprintable chars (in the ASCII sense, UTF8
* encoded) into \<hexcode>.
*/
function ldap_explode_dn_patch($dn,$with_attrib) {
$result = ldap_explode_dn($dn,$with_attrib);
if (! $result)
return null;
# translate hex code into ascii again
foreach ($result as $key => $value) {
$result[$key] = preg_replace_callback(
"/\\\([0-9A-Fa-f]{2})/",
function ($matches) {
return chr(hexdec($matches[1]));
},
$value
);
}
return $result;
}
/**
* Explode a DN into an array of its RDN parts.
*
@@ -2471,6 +2713,9 @@ function pla_explode_dn($dn,$with_attributes=0) {
global $CACHE;
if (is_null($dn))
$dn = '';
if (isset($CACHE['explode'][$dn][$with_attributes])) {
if (DEBUG_ENABLED)
debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__,
@@ -2482,8 +2727,8 @@ function pla_explode_dn($dn,$with_attributes=0) {
$dn = addcslashes($dn,'<>+";');
# split the dn
$result[0] = ldap_explode_dn(dn_escape($dn),0);
$result[1] = ldap_explode_dn(dn_escape($dn),1);
$result[0] = ldap_explode_dn_patch(dn_escape($dn),0);
$result[1] = ldap_explode_dn_patch(dn_escape($dn),1);
if (! $result[$with_attributes]) {
if (DEBUG_ENABLED)
debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__);
@@ -2542,12 +2787,22 @@ function dn_unescape($dn) {
$a = array();
foreach ($dn as $key => $rdn)
$a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn);
$a[$key] = preg_replace_callback('/\\\([0-9A-Fa-f]{2})/',
function ($r) {
return chr(hexdec($r[1]));
},
$rdn
);
return $a;
} else {
return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn);
return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/',
function ($r) {
return chr(hexdec($r[1]));
},
$dn
);
}
}
@@ -2560,35 +2815,21 @@ function dn_unescape($dn) {
* @return string The URL to the requested item.
*/
function get_href($type,$extra_info='') {
$sf = 'https://sourceforge.net';
$pla = 'http://phpldapadmin.sourceforge.net';
$group_id = '61828';
$bug_atid = '498546';
$rfe_atid = '498549';
$forum_id = 'phpldapadmin-users';
switch($type) {
case 'add_bug':
return sprintf('%s/tracker/?func=add&amp;group_id=%s&amp;atid=%s',$sf,$group_id,$bug_atid);
return 'https://github.com/leenooks/phpLDAPadmin/issues';
case 'add_rfe':
return sprintf('%s/tracker/?func=add&amp;group_id=%s&amp;atid=%s',$sf,$group_id,$rfe_atid);
return 'https://github.com/leenooks/phpLDAPadmin/issues';
case 'credits':
return sprintf('%s/Credits',$pla);
case 'documentation':
return sprintf('%s/Documentation',$pla);
case 'donate':
return sprintf('%s/donate/index.php?group_id=%s',$sf,$group_id);
return 'https://sourceforge.net/donate/index.php?group_id=61828';
case 'forum':
return sprintf('%s/mailarchive/forum.php?forum_name=%s',$sf,$forum_id);
case 'logo':
if (! isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on')
$proto = 'http';
else
$proto = 'https';
return isset($_SESSION) && ! $_SESSION[APPCONFIG]->getValue('appearance','remoteurls') ? '' : sprintf('%s://sflogo.sourceforge.net/sflogo.php?group_id=%s&amp;type=10',$proto,$group_id);
case 'sf':
return sprintf('%s/projects/phpldapadmin',$sf);
return 'https://stackoverflow.com/questions/tagged/phpldapadmin';
case 'web':
return sprintf('%s',$pla);
default:
@@ -2779,7 +3020,7 @@ function draw_formatted_dn($server,$entry) {
$formats = $_SESSION[APPCONFIG]->getValue('appearance','tree_display_format');
foreach ($formats as $format) {
foreach ($formats as $format) {
$has_none = false;
preg_match_all('/%[a-zA-Z_0-9]+/',$format,$tokens);
$tokens = $tokens[0];
@@ -3105,4 +3346,30 @@ function isAjaxEnabled() {
else
return false;
}
/**
* Check if user is a robot with reCAPTCHA
**/
function IsRobot($gResponse){
$isRobot = true;
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = array(
'secret' => $_SESSION[APPCONFIG]->getValue('session','reCAPTCHA-key-server'),
'response' => $gResponse
);
$options = array(
'http' => array (
'method' => 'POST','header' =>
'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$verify = file_get_contents($url, false, $context);
$captcha_success = json_decode($verify);
if ($captcha_success->success) {
$isRobot = false;
}
return $isRobot;
}
?>

View File

@@ -32,7 +32,7 @@
* element priority. 1 otherwise.
*/
function sort_array_by_priority($a,$b) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',257,0,__FILE__,__LINE__,__METHOD__,$fargs);
return (($a['priority'] < $b['priority']) ? -1 : 1 );
@@ -68,7 +68,7 @@ function run_hook($hook_name,$args) {
/* Execution of procedures attached is done using a numeric order
* since all procedures have been attached to the hook with a
* numerical weight. */
while (list($key,$hook) = each($hooks[$hook_name])) {
foreach ($hooks[$hook_name] as $key=>$hook) {
if (DEBUG_ENABLED)
debug_log('Calling HOOK Function (%s)(%s)',257,0,__FILE__,__LINE__,__METHOD__,
$hook['hook_function'],$args);
@@ -159,7 +159,7 @@ function remove_hook($hook_name,$hook_function,$priority,$rollback_function) {
if (array_key_exists($hook_name,$_SESSION[APPCONFIG]->hooks)) {
reset($_SESSION[APPCONFIG]->hooks[$hook_name]);
while (list($key,$hook) = each($_SESSION[APPCONFIG]->hooks[$hook_name])) {
foreach ($_SESSION[APPCONFIG]->hooks[$hook_name] as $key=>$hook) {
if (($priority >= 0 && $priority == $hook['priority']) ||
($hook_function && $hook_function == $hook['hook_function']) ||
($rollback_function && $rollback_function == $hook['rollback_function'])) {

View File

@@ -215,7 +215,7 @@ class ImportLDIF extends Import {
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
$this->template->setDN($dn);
$this->template->accept();
$this->template->accept(false,true);
return $this->getModifyDetails($lines);
@@ -511,7 +511,7 @@ class ImportLDIF extends Import {
case 'delete':
$deleteattr = false;
if ($key = array_search($attribute_value_part,$attribute->getValues()))
if (($key = array_search($attribute_value_part,$attribute->getValues())) !== false)
$attribute->delValue($key);
else
return $this->error(sprintf('%s %s',_('Delete value doesnt exist in DN'),$attribute_value_part),
@@ -589,7 +589,7 @@ class ImportLDIF extends Import {
$attrs['newsuperior'] = $attrvalue[1];
} else
return $this->error(_('A valid newsuperier attribute should be specified'),$lines);
return $this->error(_('A valid newsuperior attribute should be specified'),$lines);
} else
$attrs['newsuperior'] = $server->getContainer($this->template->getDN());

View File

@@ -48,6 +48,7 @@
1.3.6.1.1.13.1 "Pre-Read Controls" "" "The Pre-Read request control, indicates that a copy of the entry before application of update is to be returned."
1.3.6.1.1.13.2 "Post-Read Controls" "" "The Pre-Read request control, indicates that a copy of the entry before application of update is to be returned."
1.3.6.1.1.14 "Modify-Increment Extension" "RFC 4525" "An extension to the Lightweight Directory Access Protocol (LDAP) Modify operation to support an increment capability."
1.3.6.1.1.22 "Don't Use Copy Control" "RFC 9171" "When the control is attached to an LDAP request, the requested operation MUST NOT be performed on copied information. That is, the requested operation MUST be performed on original information."
1.3.6.1.4.1.42.2.27.8.5.1 "passwordPolicyRequest"
1.3.6.1.4.1.42.2.27.9.5.2 "GetEffectiveRights control" "" "May be used to determine what operations a given user may perform on a specified entry."
1.3.6.1.4.1.1466.101.119.1 "Dynamic Directory Services Refresh Request" "RFC 2589"

View File

@@ -323,7 +323,7 @@ class page {
printf('<tr class="foot"><td><small>%s</small></td><td colspan="2"><div id="ajFOOT">%s</div>%s</td></tr>',
isCompress() ? '[C]' : '&nbsp;',
app_version(),
get_href('logo') ? sprintf('<a href="%s"><img src="%s" alt="SourceForge.net Logo" style="border: 0px;" /></a>',get_href('sf'),get_href('logo')) : '&nbsp;');
'&nbsp;');
}
/**
@@ -375,6 +375,15 @@ class page {
'TREE'=>true,
'FOOT'=>true
);
if (isset($_SESSION) && $_SESSION[APPCONFIG]->getValue('appearance','minimalMode')) {
$display = array(
'HEAD'=>false,
'CONTROL'=>false,
'TREE'=>true,
'FOOT'=>false
);
}
$display = array_merge($display,$filter);

View File

@@ -18,11 +18,11 @@
*/
abstract class SchemaItem {
# The schema item's name.
protected $name = null;
protected $name = '';
# The OID of this schema item.
private $oid = null;
# The description of this schema item.
protected $description = null;
protected $description = '';
# Boolean value indicating whether this objectClass is obsolete
private $is_obsolete = false;
@@ -703,7 +703,7 @@ class ObjectClass_ObjectClassAttribute {
*/
class AttributeType extends SchemaItem {
# The attribute from which this attribute inherits (if any)
private $sup_attribute = null;
private $sup_attribute = '';
# The equality rule used
private $equality = null;
# The ordering of the attributeType
@@ -711,8 +711,8 @@ class AttributeType extends SchemaItem {
# Boolean: supports substring matching?
private $sub_str = null;
# The full syntax string, ie 1.2.3.4{16}
private $syntax = null;
private $syntax_oid = null;
private $syntax = '';
private $syntax_oid = '';
# boolean: is single valued only?
private $is_single_value = false;
# boolean: is collective?
@@ -726,7 +726,7 @@ class AttributeType extends SchemaItem {
# The max number of characters this attribute can be
private $max_length = null;
# A string description of the syntax type (taken from the LDAPSyntaxes)
private $type = null;
private $type = '';
# An array of objectClasses which use this attributeType (must be set by caller)
private $used_in_object_classes = array();
# A list of object class names that require this attribute type.
@@ -1327,7 +1327,7 @@ class Syntax extends SchemaItem {
*/
class MatchingRule extends SchemaItem {
# This rule's syntax OID
private $syntax = null;
private $syntax = '';
# An array of attribute names who use this MatchingRule
private $used_by_attrs = array();

View File

@@ -57,7 +57,7 @@ abstract class xmlTemplates {
'type'=>'info','special'=>true));
$changed = true;
eval(sprintf('$this->templates[$index] = new %s($this->server_id,$template->getName(false),$template->getFileName(),$template->getType(),$index);',$class['name']));
$this->templates[$index] = new $class['name']($this->server_id,$template->getName(false),$template->getFileName(),$template->getType(),$index);
}
}
@@ -87,7 +87,7 @@ abstract class xmlTemplates {
if (! in_array($filename,$this->getTemplateFiles())) {
$templatename = preg_replace('/.xml$/','',$file);
eval(sprintf('$this->templates[$index] = new %s($this->server_id,$templatename,$filename,$type,$index);',$class['name']));
$this->templates[$index] = new $class['name']($this->server_id,$templatename,$filename,$type,$index);
$index++;
$changed = true;
@@ -129,7 +129,7 @@ abstract class xmlTemplates {
# Store the template
$templatename = preg_replace('/.xml$/','',$file);
eval(sprintf('$this->templates[$counter] = new %s($this->server_id,$templatename,$filename,$type,$counter);',$class['name']));
$this->templates[$counter] = new $class['name']($this->server_id,$templatename,$filename,$type,$counter);
$counter++;
}
}
@@ -140,7 +140,7 @@ abstract class xmlTemplates {
if ($changed) {
masort($this->templates,'title');
set_cached_item($server_id,$class['item'],'null',$this->templates);
set_cached_item($server_id,$this->templates,$class['item'],'null');
}
}
@@ -230,7 +230,7 @@ abstract class xmlTemplates {
return clone $template;
# If we get here, the template ID didnt exist, so return a blank template, which be interpreted as the default template
eval(sprintf('$object = new %s($this->server_id,null,null,"default");',$class['name']));
$object = new $class['name']($this->server_id,'',null,'default');
return $object;
}
@@ -272,7 +272,7 @@ abstract class xmlTemplate {
# The TEMPLATE attributes as per the template definition, or the DN entry
protected $attributes = array();
public function __construct($server_id,$name=null,$filename=null,$type=null,$id=null) {
public function __construct($server_id,$name='',$filename=null,$type=null,$id=null) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs);
@@ -437,6 +437,12 @@ abstract class xmlTemplate {
# Initialise the Attribute Factory.
$attribute_factory = new AttributeFactory();
if (preg_match('/;/',$name))
system_message(array(
'title'=>'phpLDAPadmin doesnt support RFC3866.',
'body'=>sprintf('%s {%s} (%s)','PLA might not do what you expect...',$name,(is_array($value) ? serialize($value) : $value)),
'type'=>'warn'));
# If there isnt a schema item for this attribute
$attribute = $attribute_factory->newAttribute($name,$value,$server->getIndex(),$source);
@@ -444,11 +450,6 @@ abstract class xmlTemplate {
if (is_null($attrid))
array_push($this->attributes,$attribute);
else
debug_dump_backtrace(sprintf('There was a request to add an attribute (%s), but it was already defined? (%s)',$attrid,__METHOD__),true);
if ($this->getID() == 'none')
usort($this->attributes,'sortAttrs');
return $attribute;
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More