Commit 06b4a6a8 authored by benoit manager's avatar benoit manager

Merge branch '1.2.1-fixes' into 'master'

Merge 1.2.1 fixes into master

See merge request fusiondirectory/fd!374
parents 92502531 9fb29eee
......@@ -207,3 +207,5 @@ documentation and additional help.
* Mathias Soupault <mathias.soupault@inalco.fr>
Making supannAliasLogin usage possible in password recovery
* Patzke Thomas <thomas.patzke2@thyssenkrupp.com>
Security and vulnerabitity testing
## %"FusionDirectory 1.2.2" - 2018-08-16
### Added
#### fusiondirectory-plugins
- fd-plugins#5821 Add LUKS section to FAI disk entry
### Changed
#### fusiondirectory-plugins
- fd-plugins#5836 random_int should be used instead of mt_rand
- fd-plugins#5840 Duplicated value in affiliation file
### Fixed
#### fusiondirectory
- fd#5730 PHP error when I deactivate "opsi client" tab on a workstation
- fd#5789 LDIF import can trigger PHP errors on empty file
- fd#5816 Blacklist is not reset correctly for UserAttribute
- fd#5824 LDIF generation does not respect STARTTLS setting
- fd#5846 Samba groups are not showing in dashboard
- fd#5850 Config insertion LDAP errors from setup are not shown
- fd#5851 Creating a user from a template with a non-existing group crashes
- fd#5864 Name field for countries should be limited to two characters
- fd#5868 HTML is not escaped in departments descriptions
#### fusiondirectory-plugins
- fd-plugins#5719 Locale issues in the fai plugin
- fd-plugins#5741 Reference tab on the OPSI profile is not showing objects reference
- fd-plugins#5810 WebService should not return session cookie
- fd-plugins#5827 Fatal error in opsiProfile when OPSI server is not found in the LDAP
- fd-plugins#5828 supannCodeEntite should allow uppercase as well
- fd-plugins#5832 Copy/pasting of Samba groups fails
- fd-plugins#5833 Error in supann tab when we use a template
### Security
#### fusiondirectory
- fd#5840 Security Vulnerability: Cross Site Request Forgery
- fd#5842 Security: Missing Security Headers
- fd#5843 Security: Insecure Generation of Random Tokens
## %"FusionDirectory 1.2.1" - 2018-05-09
### Added
......
......@@ -2786,11 +2786,12 @@ apt-get remove fusiondirectory-plugin-kolab2-schema
### Upgrade schema2ldif
For Jessie distribution add extra repository
```shell
# fusiondirectory debian-extra repository
deb http://repos.fusiondirectory.org/debian-extra jessie main
deb http://repos.fusiondirectory.org/fusiondirectory-extra/debian-jessie/ jessie main
```
* Update the package list and upgrade schema2ldif
......@@ -2946,6 +2947,7 @@ Check that all you index still match with valid attributes present in your ldap
Open and save it back so it will use the new format
## Migrate FusionDirectory from 1.1 to 1.1.1
### New Depot Configuration
......@@ -2958,7 +2960,7 @@ For Jessie distribution add extra repository
```shell
# fusiondirectory debian-extra repository
deb http://repos.fusiondirectory.org/debian-extra jessie main
deb http://repos.fusiondirectory.org/fusiondirectory-extra/debian-jessie/ jessie main
```
* Update the package list and upgrade schema2ldif
......@@ -2990,7 +2992,14 @@ For Jessie distribution add extra repository
```shell
# fusiondirectory debian-extra repository
deb http://repos.fusiondirectory.org/debian-extra jessie main
deb http://repos.fusiondirectory.org/fusiondirectory-extra/debian-jessie/ jessie main
```
For Stretch distribution add extra repository
```shell
# fusiondirectory debian-extra repository
deb http://repos.fusiondirectory.org/fusiondirectory-extra/debian-stretch/ stretch main
```
* Update the package list and upgrade schema2ldif
......@@ -3037,7 +3046,65 @@ fusiondirectory-insert-schema -m /etc/ldap/schema/fusiondirectory/sympa-fd.schem
* In case you use system template that have a DNS tab, you need to remake it because the separator "|" is changed to "^"
## Migrate FusionDirectory from 1.2 to 1.2.1
### Upgrade schema2ldif
For Jessie distribution add extra repository
```shell
# fusiondirectory debian-extra repository
deb http://repos.fusiondirectory.org/fusiondirectory-extra/debian-jessie/ jessie main
```
For Stretch distribution add extra repository
```shell
# fusiondirectory debian-extra repository
deb http://repos.fusiondirectory.org/fusiondirectory-extra/debian-stretch/ stretch main
```
* Update the package list and upgrade schema2ldif
```shell
apt-get update
apt-get install schema2ldif
```
### Upgrade FusionDirectory first
* Upgrade FusionDirectory core package before other ones to avoid dependencies errors:
```shell
apt-get install fusiondirectory
```
* Upgrade FusionDirectory schema package too.
```shell
apt-get install fusiondirectory-schema
```
[php-cas]: http://packages.ubuntu.com/trusty/all/php-cas/download
[repo-urls]: https://documentation.fusiondirectory.org/en/dl_install
---
* Further information
To improve this piece of software, please report all kind of errors using the bug tracker
on https://forge.fusiondirectory.org
Documentation: https://documentation.fusiondirectory.org/
Mailinglist: https://lists.fusiondirectory.org/
Irc: #fusiondirectory on freenode
---
The FusionDirectory project https://www.fusiondirectory.org/
Enjoy :)
......@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "FUSIONDIRECTORY-INSERT-SCHEMA 1"
.TH FUSIONDIRECTORY-INSERT-SCHEMA 1 "2018-02-09" "FusionDirectory 1.2.1" "FusionDirectory Documentation"
.TH FUSIONDIRECTORY-INSERT-SCHEMA 1 "2018-07-25" "FusionDirectory 1.2.2" "FusionDirectory Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "FUSIONDIRECTORY-SETUP 1"
.TH FUSIONDIRECTORY-SETUP 1 "2018-02-09" "FusionDirectory 1.2.1" "FusionDirectory Documentation"
.TH FUSIONDIRECTORY-SETUP 1 "2018-08-16" "FusionDirectory 1.2.2" "FusionDirectory Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "FUSIONDIRECTORY.CONF 1"
.TH FUSIONDIRECTORY.CONF 1 "2018-02-09" "FusionDirectory 1.2.1" "FusionDirectory Documentation"
.TH FUSIONDIRECTORY.CONF 1 "2018-08-16" "FusionDirectory 1.2.2" "FusionDirectory Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......
......@@ -104,6 +104,8 @@ class standAlonePage {
load_plist();
$ssl = $this->checkForSSL();
static::securityHeaders();
}
}
......@@ -221,6 +223,13 @@ class standAlonePage {
return $params;
}
static function securityHeaders()
{
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: deny');
}
static function generateRandomHash()
{
/* Generate a very long random value */
......@@ -228,9 +237,8 @@ class standAlonePage {
$base = 'ABCDEFGHKLMNOPQRSTWXYZabcdefghjkmnpqrstwxyz123456789';
$max = strlen($base) - 1;
$randomhash = '';
mt_srand((double) microtime() * 1000000);
while (strlen($randomhash) < $len + 1) {
$randomhash .= $base{mt_rand(0, $max)};
$randomhash .= $base{random_int(0, $max)};
}
return $randomhash;
}
......
......@@ -24,7 +24,12 @@ require_once ("../include/php_setup.inc");
require_once ("functions.inc");
require_once ("variables.inc");
require_once ("class_logging.inc");
header("Content-type: text/html; charset=UTF-8");
/* Set headers */
header('Content-type: text/html; charset=UTF-8');
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: deny');
/* Display the login page and exit() */
function displayLogin()
......
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2003-2010 Cajus Pollmeier
Copyright (C) 2011-2016 FusionDirectory
Copyright (C) 2011-2018 FusionDirectory
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -28,8 +27,11 @@ require_once ("../include/php_setup.inc");
require_once ("functions.inc");
require_once ("variables.inc");
/* Set header */
header("Content-type: text/html; charset=UTF-8");
/* Set headers */
header('Content-type: text/html; charset=UTF-8');
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: deny');
/* Set the text domain as 'fusiondirectory' */
$domain = 'fusiondirectory';
......@@ -54,6 +56,8 @@ if (!session::global_is_set('connected')) {
exit;
}
CSRFProtection::check();
$ui = session::global_get('ui');
$config = session::global_get('config');
......@@ -324,7 +328,8 @@ if (session::is_set('errors') && session::get('errors') != "") {
$focus = '<script type="text/javascript">';
$focus .= 'next_msg_dialog();';
$focus .= '</script>';
$smarty->assign("focus", $focus);
$smarty->assign('focus', $focus);
$smarty->assign('CSRFtoken', CSRFProtection::getToken());
/* Set channel if needed */
//TODO: * move all global session calls to global_
......
......@@ -35,8 +35,11 @@ require_once("../setup/class_setupStepMigrate.inc");
require_once("../setup/class_setupStepFinish.inc");
/* Set header */
header("Content-type: text/html; charset=UTF-8");
/* Set headers */
header('Content-type: text/html; charset=UTF-8');
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: deny');
/* Set cookie lifetime to one day (The parameter is in seconds ) */
session_set_cookie_params(24 * 60 * 60);
......@@ -49,6 +52,8 @@ session::start();
session::global_set('DEBUGLEVEL', 0);
session::set('errorsAlreadyPosted', array());
CSRFProtection::check();
/* Attribute initialization, reset errors */
reset_errors();
......@@ -124,6 +129,7 @@ $smarty->assign("navigation", $setup->get_navigation_html());
$smarty->assign("headline_image", $setup->get_header_image());
$smarty->assign("headline", $setup->get_header_text());
$smarty->assign("focus", $focus);
$smarty->assign('CSRFtoken', CSRFProtection::getToken());
$smarty->assign("msg_dialogs", msg_dialog::get_dialogs());
if ($error_collector != "") {
......
......@@ -55,6 +55,7 @@
{$errors}
{$focus}
<input type="hidden" name="php_c_check" value="1"/>
<input type="hidden" name="CSRFtoken" value="{$CSRFtoken}"/>
</form>
......
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2017-2018 FusionDirectory
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
class CSRFProtection
{
public static function check()
{
if (empty($_POST)) {
return;
}
if (empty($_POST['CSRFtoken'])) {
throw new FusionDirectoryException('CSRF protection token missing');
}
static::checkHeaders();
if ($_POST['CSRFtoken'] !== static::getToken()) {
throw new FusionDirectoryException('CSRF protection token invalid');
}
}
public static function getToken()
{
if (!session::is_set('CSRFtoken')) {
session::set('CSRFtoken', standAlonePage::generateRandomHash());
}
return session::get('CSRFtoken');
}
public static function checkHeaders()
{
$origin = FALSE;
if (!empty($_SERVER['HTTP_ORIGIN'])) {
$origin = $_SERVER['HTTP_ORIGIN'];
} elseif (!empty($_SERVER['HTTP_REFERER'])) {
$origin = $_SERVER['HTTP_REFERER'];
}
if ($origin) {
$origin = preg_replace('|^[^/]+://([^/]+)(/.*)?$|', '\1', $origin);
$target = FALSE;
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$target = $_SERVER['HTTP_X_FORWARDED_HOST'];
} else
if (!empty($_SERVER['HTTP_HOST'])) {
$target = $_SERVER['HTTP_HOST'];
}
if ($target && !hash_equals($origin, $target)) {
throw new FusionDirectoryException('CSRF detected: origin and target are not matching ('.$origin.' != '.$target.')');
}
}
}
}
......@@ -238,9 +238,9 @@ class baseSelector
$this->tree .= "<li><a$selected $link>".
'<img class="center" '.
'src="'.htmlentities($config->department_info[$base]['img'], ENT_COMPAT, 'UTF-8').'" '.
'alt="'.$config->department_info[$base]['name'].'"/>&nbsp;'.
$this->gennonbreaks($config->department_info[$base]['name']).
($config->department_info[$base]['description'] == '' ? '' : '&nbsp;<span class="informal">['.$this->gennonbreaks($config->department_info[$base]['description']).']</span>').
'alt="'.htmlentities($config->department_info[$base]['name'], ENT_COMPAT, 'UTF-8').'"/>&nbsp;'.
$this->escape($config->department_info[$base]['name']).
(($config->department_info[$base]['description'] == '') ? '' : '&nbsp;<span class="informal">['.$this->escape($config->department_info[$base]['description']).']</span>').
'</a>';
$last_indent = $indent;
......@@ -267,13 +267,13 @@ class baseSelector
/*!
* \brief Replace all space of the string by non-breaking space
* \brief Replace all space of the string by non-breaking space and escapes HTML
*
* \param String $string The string which his space will be replaced
*/
function gennonbreaks($string)
function escape($string)
{
return str_replace('-', '&#8209;', str_replace(' ', '&nbsp;', $string));
return str_replace(' ', '&nbsp;', htmlentities($string, ENT_COMPAT, 'UTF-8'));
}
/*!
......
......@@ -985,7 +985,7 @@ class LDAP
$admin = escapeshellarg($this->binddn);
$filter = escapeshellarg($filter);
$cmd = "ldapsearch -x -LLLL -D {$admin} {$filter} {$limit} {$scope} -H {$host} -b {$dn} -w {$pwd} ";
$cmd = 'ldapsearch'.($this->tls ? ' -ZZ' : '')." -x -LLLL -D {$admin} {$filter} {$limit} {$scope} -H {$host} -b {$dn} -w {$pwd} ";
// Create list of process pipes
$descriptorspec = array(
......@@ -1052,8 +1052,9 @@ class LDAP
}
/* Joining lines */
$line = NULL;
$entry = array();
$line = NULL;
$entry = array();
$entries = array();
$entryStart = -1;
foreach ($fileLines as $lineNumber => $fileLine) {
if (preg_match('/^ /', $fileLine)) {
......@@ -1123,6 +1124,8 @@ class LDAP
throw new LDIFImportException(sprintf(_('Error while importing dn: "%s", please check your LDIF from line %s on!'), $entry['dn'][0], $startLine));
}
}
return count($entries);
}
/*! \brief Function to Imports a single entry
......
......@@ -310,7 +310,7 @@ class templateHandling
$length = 8;
$chars = 'b';
if (count($args) >= 2) {
$length = mt_rand($args[0], $args[1]);
$length = random_int($args[0], $args[1]);
if (count($args) >= 3) {
$chars = $args[2];
}
......@@ -322,11 +322,11 @@ class templateHandling
switch ($chars) {
case 'd':
/* digits */
$res .= (string)rand(0, 9);
$res .= (string)random_int(0, 9);
break;
case 'l':
/* letters */
$nb = mt_rand(65, 116);
$nb = random_int(65, 116);
if ($nb > 90) {
/* lowercase */
$nb += 6;
......@@ -336,7 +336,7 @@ class templateHandling
case 'b':
/* both */
default:
$nb = mt_rand(65, 126);
$nb = random_int(65, 126);
if ($nb > 116) {
/* digit */
$nb = (string)($nb - 117);
......
......@@ -175,25 +175,6 @@ function load_plist ($ldap_available = TRUE)
return session::global_get('plist');
}
/*!
* \brief Create seed with microseconds
*
* Example:
* \code
* srand(make_seed());
* $random = rand();
* \endcode
*
* \return float a floating point number which can be used to feed srand() with it
*/
function make_seed()
{
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}
/*!
* \brief Debug level action
*
......@@ -1566,8 +1547,7 @@ function gen_uids($rule, $attributes)
$size = preg_replace('/^.*{id#(\d+)}.*$/', '\\1', $uid);
while (TRUE) {
mt_srand((double)microtime() * 1000000);
$number = sprintf("%0".$size."d", mt_rand(0, pow(10, $size) - 1));
$number = sprintf("%0".$size."d", random_int(0, pow(10, $size) - 1));
$res = preg_replace('/{id#(\d+)}/', $number, $uid);
$ldap->search('(uid='.ldap_escape_f(preg_replace('/[{}]/', '', $res)).')', array('dn'));
if ($ldap->count() == 0) {
......@@ -2662,6 +2642,38 @@ if (!function_exists('ldap_escape')) {
}
}
if (!function_exists('random_int')) {
// PHP<7, we fallback on openssl_random_pseudo_bytes
function random_int($min, $max)
{
$range = $max - $min;
if ($range <= 0) {
throw new Exception('Invalid range passed to random_int');
}
$log = log($range, 2);
// length in bytes
$nbBytes = (int) ($log / 8) + 1;
// length in bits
$nbBits = (int) $log + 1;
// set all lower bits to 1
$filter = pow(2, $nbBits) - 1;
if ($filter >= PHP_INT_MAX) {
$filter = PHP_INT_MAX;
}
do {
$randomBytes = openssl_random_pseudo_bytes($nbBytes, $strong);
if (!$strong || ($randomBytes === FALSE)) {
throw new Exception('Failed to get random bytes');
}
$rnd = hexdec(bin2hex($randomBytes));
// discard irrelevant bits
$rnd = $rnd & $filter;
} while ($rnd > $range);
return $min + $rnd;
}
}
function ldap_escape_f($str, $ignore = '')
{
return ldap_escape($str, $ignore, LDAP_ESCAPE_FILTER);
......
......@@ -55,8 +55,7 @@ class passwordMethodsmd5 extends passwordMethod
*/
function generate_hash($pwd)
{
mt_srand(microtime() * 10000000);
$salt0 = substr(pack('h*', md5(mt_rand())), 0, 8);
$salt0 = substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8);
$salt = substr(pack('H*', md5($salt0 . $pwd)), 0, 4);
$hash = '{SMD5}'.base64_encode(pack('H*', md5($pwd . $salt)) . $salt);
return $hash;
......
......@@ -56,12 +56,12 @@ class passwordMethodssha extends passwordMethod
function generate_hash($pwd)
{
if (function_exists('sha1')) {
$salt = substr(pack('h*', md5(mt_rand())), 0, 8);
$salt = substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8);
$salt = substr(pack('H*', sha1($salt.$pwd)), 0, 4);
$pwd = '{SSHA}'.base64_encode(pack('H*', sha1($pwd.$salt)).$salt);
return $pwd;
} elseif (function_exists('mhash')) {
$salt = mhash_keygen_s2k(MHASH_SHA1, $pwd, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
$salt = mhash_keygen_s2k(MHASH_SHA1, $pwd, substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8), 4);
$pwd = '{SSHA}'.base64_encode(mhash(MHASH_SHA1, $pwd.$salt).$salt);
} else {
msg_dialog::display(_('Configuration error'), msgPool::missingext('mhash'), ERROR_DIALOG);
......
......@@ -309,8 +309,7 @@ class ImageAttribute extends FileAttribute
$this->setValue($this->inputValue($this->getValue()));
$id = $this->getHtmlId();
// Just to be sure the image is not cached
srand((double)microtime() * 1000000);
$key = $this->getLdapName().rand(0, 10000);
$key = $this->getLdapName().random_int(0, 10000);
$display = '<img id="'.$id.'_img"'.
($this->disabled ? 'disabled="disabled"' : '').
' src="getbin.php?key='.$key.'"'.
......
......@@ -566,7 +566,18 @@ class Attribute
{
if ($this->visible) {
if ($readOnly) {
$input = '{literal}'.htmlentities($this->getValue(), ENT_COMPAT, 'UTF-8').'{/literal}';
$value = $this->getValue();
if (is_array($value)) {
$input = '{literal}'.implode('<br/>', array_map(
function ($v)
{
return htmlentities($v, ENT_COMPAT, 'UTF-8');
},
$value
)).'{/literal}';
} else {
$input = '{literal}'.htmlentities($value, ENT_COMPAT, 'UTF-8').'{/literal}';
}
} elseif (is_object($this->plugin) && $this->plugin->is_template) {
$input = $this->renderTemplateInput();
} else {
......
......@@ -94,6 +94,13 @@ class SingleUserSelectDialog extends GenericDialog
{
protected $dialogClass = 'singleUserSelect';
function dialog_execute ()
{
session::set('filterBlacklist', $this->attribute->getFilterBlackList());
session::set('filterWhitelist', $this->attribute->getFilterWhiteList());
return parent::dialog_execute();
}
function handle_finish ()
{
$result = $this->dialog->detectPostActions();
......@@ -628,6 +635,16 @@ class DialogButtonAttribute extends ButtonAttribute
$this->plugin->openDialog(new $this->dialogClass($this->plugin, $this));
}
}
function getFilterBlackList ()
{
return array();
}
function getFilterWhiteList ()
{
return array();
}
}
class UserAttribute extends DialogButtonAttribute
......
......@@ -63,7 +63,7 @@ define("FPDF_FONTPATH", "/usr/share/php/fpdf/font/"); /*! Define fpdf font path
/*!
* \brief FusionDirectory Version
*/
define ("FD_VERSION", "1.2.1"); /*! Define FusionDirectory version */
define ("FD_VERSION", "1.2.2"); /*! Define FusionDirectory version */
/*!
* \brief FusionDirectory config object RDN
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.