store sambaPasswordHistory

This commit is contained in:
Roland Gruber 2016-05-20 19:38:36 +02:00
parent cf5132745d
commit bdae11ff4a
3 changed files with 133 additions and 3 deletions

View File

@ -385,7 +385,9 @@ function search_domains($server = null, $suffix = null) {
} }
$ret = array(); $ret = array();
$attr = array("DN", "sambaDomainName", "sambaSID", "sambaNextRid", "sambaNextGroupRid", $attr = array("DN", "sambaDomainName", "sambaSID", "sambaNextRid", "sambaNextGroupRid",
"sambaNextUserRid", "sambaAlgorithmicRidBase", 'sambaMinPwdAge', 'sambaMaxPwdAge'); "sambaNextUserRid", "sambaAlgorithmicRidBase", 'sambaMinPwdAge', 'sambaMaxPwdAge',
'sambaPwdHistoryLength'
);
if ($server == null) { if ($server == null) {
$server = $_SESSION['ldap']->server(); $server = $_SESSION['ldap']->server();
} }
@ -402,6 +404,7 @@ function search_domains($server = null, $suffix = null) {
if (isset($units[$i]['sambaalgorithmicridbase'][0])) $ret[$i]->RIDbase = $units[$i]['sambaalgorithmicridbase'][0]; if (isset($units[$i]['sambaalgorithmicridbase'][0])) $ret[$i]->RIDbase = $units[$i]['sambaalgorithmicridbase'][0];
if (isset($units[$i]['sambaminpwdage'][0])) $ret[$i]->minPwdAge = $units[$i]['sambaminpwdage'][0]; if (isset($units[$i]['sambaminpwdage'][0])) $ret[$i]->minPwdAge = $units[$i]['sambaminpwdage'][0];
if (isset($units[$i]['sambamaxpwdage'][0])) $ret[$i]->maxPwdAge = $units[$i]['sambamaxpwdage'][0]; if (isset($units[$i]['sambamaxpwdage'][0])) $ret[$i]->maxPwdAge = $units[$i]['sambamaxpwdage'][0];
if (isset($units[$i]['sambapwdhistorylength'][0])) $ret[$i]->pwdHistoryLength = $units[$i]['sambapwdhistorylength'][0];
} }
return $ret; return $ret;
} }
@ -439,6 +442,9 @@ class samba3domain {
/** seconds after the password must be changed */ /** seconds after the password must be changed */
public $maxPwdAge; public $maxPwdAge;
/** password history length */
public $pwdHistoryLength;
} }
/** /**

View File

@ -4,7 +4,7 @@ $Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2006 Tilo Lutz Copyright (C) 2003 - 2006 Tilo Lutz
2005 - 2015 Roland Gruber 2005 - 2016 Roland Gruber
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -157,7 +157,7 @@ class sambaSamAccount extends baseModule implements passwordService {
'sambaLogonTime', 'sambaLogoffTime', 'sambaKickoffTime', 'sambaAcctFlags', 'sambaLogonTime', 'sambaLogoffTime', 'sambaKickoffTime', 'sambaAcctFlags',
'sambaPwdLastSet', 'displayName', 'sambaHomePath', 'sambaHomeDrive', 'sambaLogonScript', 'sambaProfilePath', 'sambaPwdLastSet', 'displayName', 'sambaHomePath', 'sambaHomeDrive', 'sambaLogonScript', 'sambaProfilePath',
'sambaUserWorkstations', 'sambaPrimaryGroupSID', 'sambaDomainName', 'sambaLogonHours', 'sambaMungedDial', 'sambaUserWorkstations', 'sambaPrimaryGroupSID', 'sambaDomainName', 'sambaLogonHours', 'sambaMungedDial',
'sambaPwdCanChange', 'sambaPwdMustChange'); // sambaPwdCanChange/sambaPwdMustChange only for extension removal 'sambaPasswordHistory', 'sambaPwdCanChange', 'sambaPwdMustChange'); // sambaPwdCanChange/sambaPwdMustChange only for extension removal
// PHP extensions // PHP extensions
$return['extensions'] = array('hash', 'iconv'); $return['extensions'] = array('hash', 'iconv');
// profile options // profile options
@ -2396,6 +2396,41 @@ class sambaSamAccount extends baseModule implements passwordService {
if ($forcePasswordChange) { if ($forcePasswordChange) {
$this->attributes['sambaPwdLastSet'][0] = '0'; $this->attributes['sambaPwdLastSet'][0] = '0';
} }
// password history entry
$sambaDomains = $this->getDomains();
if (sizeof($sambaDomains) > 0) {
if (isset($this->attributes['sambaSID'][0]) && $this->attributes['sambaSID'][0] != '') {
$domainSID = substr($this->attributes['sambaSID'][0], 0, strrpos($this->attributes['sambaSID'][0], "-"));
}
$historyLength = 0;
for ($i = 0; $i < count($sambaDomains); $i++) {
if (!empty($domainSID)) {
if (($domainSID == $sambaDomains[$i]->SID) && !empty($sambaDomains[$i]->pwdHistoryLength)) {
$historyLength = $sambaDomains[$i]->pwdHistoryLength;
break;
}
}
elseif (isset($this->attributes['sambaDomainName'][0]) && ($this->attributes['sambaDomainName'][0]!='')) {
if (($this->attributes['sambaDomainName'][0] == $sambaDomains[$i]->name) && !empty($sambaDomains[$i]->pwdHistoryLength)) {
$historyLength = $sambaDomains[$i]->pwdHistoryLength;
break;
}
}
}
if (!empty($historyLength) && is_numeric($historyLength) && ($historyLength > 0)) {
if (!empty($this->orig['sambaPasswordHistory'][0])) {
$this->attributes['sambaPasswordHistory'] = $this->orig['sambaPasswordHistory'];
}
else {
$this->attributes['sambaPasswordHistory'] = array();
}
while (sizeof($this->attributes['sambaPasswordHistory']) > ($historyLength - 1)) {
array_pop($this->attributes['sambaPasswordHistory']);
}
$this->attributes['sambaPasswordHistory'][] = sambaSamAccount::createHistoryEntry($password);
$this->attributes['sambaPasswordHistory'] = array_values($this->attributes['sambaPasswordHistory']);
}
}
return array(); return array();
} }
@ -2581,6 +2616,41 @@ class sambaSamAccount extends baseModule implements passwordService {
$this->attributes['sambaAcctFlags'][0] = str_replace(']', ' ]', $this->attributes['sambaAcctFlags'][0]); $this->attributes['sambaAcctFlags'][0] = str_replace(']', ' ]', $this->attributes['sambaAcctFlags'][0]);
} }
/**
* Creates the value to store in sambaPasswordHistory attribute.
*
* @param String $password password
* @return String value for sambaPasswordHistory
*/
public static function createHistoryEntry($password) {
if (empty($password)) {
return null;
}
$salt = generateSalt(16);
$saltHex = bin2hex($salt);
$md4hash = ntPassword($password);
$md5hash = md5($salt . hex2bin($md4hash));
return strtoupper($saltHex . $md5hash);
}
/**
* Checks if the given password matches the history entry.
*
* @param String $password password
* @param String $historyEntry sambaPasswordHistory entry
* @return Boolean entry matches password
*/
public static function validateHistoryEntry($password, $historyEntry) {
if (empty($historyEntry) || (strlen($historyEntry) != 64)) {
return false;
}
$salt = hex2bin(substr($historyEntry, 0, 32));
$hash = substr($historyEntry, 32, 32);
$md4hash = ntPassword($password);
$md5hash = md5($salt . hex2bin($md4hash));
return strtolower($md5hash) == strtolower($hash);
}
} }
?> ?>

View File

@ -0,0 +1,54 @@
<?php
/*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2016 Roland Gruber
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
include_once (dirname ( __FILE__ ) . '/../../../lib/baseModule.inc');
include_once (dirname ( __FILE__ ) . '/../../../lib/modules.inc');
include_once (dirname ( __FILE__ ) . '/../../../lib/passwordExpirationJob.inc');
include_once (dirname ( __FILE__ ) . '/../../../lib/modules/sambaSamAccount.inc');
/**
* Checks the shadow expire job.
*
* @author Roland Gruber
*
*/
class SambaSamAccountTest extends PHPUnit_Framework_TestCase {
public function testValidateHistoryEntry() {
$this->assertFalse(sambaSamAccount::validateHistoryEntry("password", ""));
$this->assertFalse(sambaSamAccount::validateHistoryEntry("password", "123"));
$this->assertFalse(sambaSamAccount::validateHistoryEntry("password", "1234567890123456789012345678901234567890"));
$this->assertFalse(sambaSamAccount::validateHistoryEntry("password", "12345678901234567890123456789012"));
$this->assertTrue(sambaSamAccount::validateHistoryEntry("password", "8E36265C3B44B640CCB365040DE68E5A4BF09D61C23AB4A0CC9D1866E1C69191"));
}
public function testCreateHistoryEntry() {
$this->assertEquals(sambaSamAccount::createHistoryEntry(""), null);
$password = 'password123';
$this->assertTrue(sambaSamAccount::validateHistoryEntry($password, sambaSamAccount::createHistoryEntry($password)));
}
}
?>