Foundation for Check Password and password functions - only Clear is currently implemented
This commit is contained in:
@@ -11,10 +11,11 @@ use App\Classes\LDAP\Schema\AttributeType;
|
||||
/**
|
||||
* Represents an attribute of an LDAP Object
|
||||
*/
|
||||
class Attribute implements \Countable, \ArrayAccess
|
||||
class Attribute implements \Countable, \ArrayAccess, \Iterator
|
||||
{
|
||||
// Attribute Name
|
||||
protected string $name;
|
||||
private int $counter = 0;
|
||||
|
||||
protected ?AttributeType $schema = NULL;
|
||||
|
||||
@@ -174,6 +175,31 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
$this->values->push($value);
|
||||
}
|
||||
|
||||
public function current(): mixed
|
||||
{
|
||||
return $this->values->get($this->counter);
|
||||
}
|
||||
|
||||
public function next(): void
|
||||
{
|
||||
$this->counter++;
|
||||
}
|
||||
|
||||
public function key(): mixed
|
||||
{
|
||||
return $this->counter;
|
||||
}
|
||||
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->values->has($this->counter);
|
||||
}
|
||||
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->counter = 0;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return $this->values->count();
|
||||
@@ -181,7 +207,7 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return ! is_null($this->values->get($offset));
|
||||
return ! is_null($this->values->has($offset));
|
||||
}
|
||||
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
|
@@ -4,7 +4,9 @@ namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Password\Base;
|
||||
use App\Classes\LDAP\Attribute;
|
||||
use App\Traits\MD5Updates;
|
||||
|
||||
@@ -14,6 +16,52 @@ use App\Traits\MD5Updates;
|
||||
final class Password extends Attribute
|
||||
{
|
||||
use MD5Updates;
|
||||
private const password_helpers = 'Classes/LDAP/Attribute/Password';
|
||||
public const commands = 'App\\Classes\\LDAP\\Attribute\\Password\\';
|
||||
|
||||
private static function helpers(): Collection
|
||||
{
|
||||
$helpers = collect();
|
||||
|
||||
foreach (preg_grep('/^([^.])/',scandir(app_path(self::password_helpers))) as $file) {
|
||||
if (($file === 'Base.php') || (! str_ends_with(strtolower($file),'.php')))
|
||||
continue;
|
||||
|
||||
$class = self::commands.preg_replace('/\.php$/','',$file);
|
||||
if ($helpers->count())
|
||||
$helpers->push('');
|
||||
|
||||
$helpers = $helpers
|
||||
->merge([$class::id()=>$class]);
|
||||
}
|
||||
|
||||
return $helpers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object that will process a password
|
||||
*
|
||||
* @param string $id
|
||||
* @return Base|null
|
||||
*/
|
||||
public static function hash(string $id): ?Attribute\Password\Base
|
||||
{
|
||||
return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an LDAP password syntax {xxx}yyyyyy, this function will return xxx
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function hash_id(string $password): string
|
||||
{
|
||||
$m = [];
|
||||
preg_match('/^{([A-Z]+)}(.*)$/',$password,$m);
|
||||
|
||||
return Arr::get($m,1,'Clear');
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
@@ -21,7 +69,8 @@ final class Password extends Attribute
|
||||
->with('o',$this)
|
||||
->with('edit',$edit)
|
||||
->with('old',$old)
|
||||
->with('new',$new);
|
||||
->with('new',$new)
|
||||
->with('helpers',static::helpers()->map(fn($item,$key)=>['id'=>$key,'value'=>$key]));
|
||||
}
|
||||
|
||||
public function render_item_old(int $key): ?string
|
||||
|
14
app/Classes/LDAP/Attribute/Password/Base.php
Normal file
14
app/Classes/LDAP/Attribute/Password/Base.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Password;
|
||||
|
||||
abstract class Base
|
||||
{
|
||||
abstract public function compare(string $source,string $compare): bool;
|
||||
abstract public function encode(string $password): string;
|
||||
|
||||
public static function id(): string
|
||||
{
|
||||
return static::key;
|
||||
}
|
||||
}
|
18
app/Classes/LDAP/Attribute/Password/Clear.php
Normal file
18
app/Classes/LDAP/Attribute/Password/Clear.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute\Password;
|
||||
|
||||
final class Clear extends Base
|
||||
{
|
||||
public const key = 'Clear';
|
||||
|
||||
public function compare(string $source,string $compare): bool
|
||||
{
|
||||
return $source === $compare;
|
||||
}
|
||||
|
||||
public function encode(string $password): string
|
||||
{
|
||||
return $password;
|
||||
}
|
||||
}
|
@@ -90,6 +90,25 @@ class HomeController extends Controller
|
||||
return $x->render();
|
||||
}
|
||||
|
||||
public function entry_password_check(Request $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($request->dn);
|
||||
$o = config('server')->fetch($dn);
|
||||
|
||||
$password = $o->getObject('userpassword');
|
||||
|
||||
$result = collect();
|
||||
foreach ($password as $key => $value) {
|
||||
$type = $password->hash_id($value);
|
||||
$compare = Arr::get($request->password,$key);
|
||||
//Log::debug(sprintf('comparing [%s] with [%s] type [%s]',$value,$compare,$type));
|
||||
|
||||
$result->push((($compare !== NULL) && Attribute\Password::hash($type)->compare($value,$compare)) ? 'OK' :'FAIL');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a confirmation to update a DN
|
||||
*
|
||||
@@ -103,9 +122,19 @@ class HomeController extends Controller
|
||||
|
||||
$o = config('server')->fetch($dn);
|
||||
|
||||
foreach ($request->except(['_token','dn']) as $key => $value)
|
||||
foreach ($request->except(['_token','dn','userpassword_hash','userpassword']) as $key => $value)
|
||||
$o->{$key} = array_filter($value);
|
||||
|
||||
// We need to process and encrypt the password
|
||||
$passwords = [];
|
||||
foreach ($request->userpassword as $key => $value) {
|
||||
if ($value) {
|
||||
$type = Arr::get($request->userpassword_hash,$key);
|
||||
array_push($passwords,Attribute\Password::hash($type)->encode($value));
|
||||
}
|
||||
}
|
||||
$o->userpassword = $passwords;
|
||||
|
||||
if (! $o->getDirty())
|
||||
return back()
|
||||
->withInput()
|
||||
|
@@ -52,11 +52,17 @@ class Entry extends Model
|
||||
|
||||
/**
|
||||
* Determine if the new and old values for a given key are equivalent.
|
||||
*
|
||||
* @todo This function barfs on language tags, eg: key = givenname;lang-ja
|
||||
*/
|
||||
protected function originalIsEquivalent(string $key): bool
|
||||
{
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
// @todo Silently ignore keys of language tags - we should work with them
|
||||
if (str_contains($key,';'))
|
||||
return TRUE;
|
||||
|
||||
return ((! array_key_exists($key,$this->original)) && (! $this->objects->has($key)))
|
||||
|| (! $this->getObject($key)->isDirty());
|
||||
}
|
||||
|
Reference in New Issue
Block a user