Added additional password hashing functions
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 33s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m26s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 3m36s
Create Docker Image / Final Docker Image Manifest (push) Successful in 11s
All checks were successful
Create Docker Image / Test Application (x86_64) (push) Successful in 33s
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 1m26s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 3m36s
Create Docker Image / Final Docker Image Manifest (push) Successful in 11s
This commit is contained in:
parent
77a139016b
commit
d3d7881e3b
@ -6,7 +6,6 @@ use Illuminate\Contracts\View\View;
|
|||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
use App\Classes\LDAP\Attribute\Password\Base;
|
|
||||||
use App\Classes\LDAP\Attribute;
|
use App\Classes\LDAP\Attribute;
|
||||||
use App\Traits\MD5Updates;
|
use App\Traits\MD5Updates;
|
||||||
|
|
||||||
@ -28,41 +27,54 @@ final class Password extends Attribute
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
$class = self::commands.preg_replace('/\.php$/','',$file);
|
$class = self::commands.preg_replace('/\.php$/','',$file);
|
||||||
if ($helpers->count())
|
|
||||||
$helpers->push('');
|
|
||||||
|
|
||||||
$helpers = $helpers
|
$helpers = $helpers
|
||||||
->merge([$class::id()=>$class]);
|
->merge([$class::id()=>$class]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $helpers;
|
return $helpers->sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an LDAP password syntax {xxx}yyyyyy, this function will return the object for xxx
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
* @return Attribute\Password\Base|null
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function hash(string $password): ?Attribute\Password\Base
|
||||||
|
{
|
||||||
|
$m = [];
|
||||||
|
preg_match('/^{([A-Z0-9]+)}(.*)$/',$password,$m);
|
||||||
|
|
||||||
|
$hash = Arr::get($m,1,'*clear*');
|
||||||
|
|
||||||
|
if (($potential=static::helpers()->filter(fn($hasher)=>str_starts_with($hasher::id(),$hash)))->count() > 1) {
|
||||||
|
foreach ($potential as $item) {
|
||||||
|
if ($item::subid($password))
|
||||||
|
return new $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \Exception(sprintf('Couldnt figure out a password hash for %s',$password));
|
||||||
|
|
||||||
|
} elseif (! $potential->count()) {
|
||||||
|
throw new \Exception(sprintf('Couldnt figure out a password hash for %s',$password));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ($potential->pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the object that will process a password
|
* Return the object that will process a password
|
||||||
*
|
*
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return Base|null
|
* @return Attribute\Password\Base|null
|
||||||
*/
|
*/
|
||||||
public static function hash(string $id): ?Attribute\Password\Base
|
public static function hash_id(string $id): ?Attribute\Password\Base
|
||||||
{
|
{
|
||||||
return ($helpers=static::helpers())->has($id) ? new ($helpers->get($id)) : NULL;
|
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
|
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||||
{
|
{
|
||||||
return view('components.attribute.password')
|
return view('components.attribute.password')
|
||||||
@ -75,11 +87,17 @@ final class Password extends Attribute
|
|||||||
|
|
||||||
public function render_item_old(int $key): ?string
|
public function render_item_old(int $key): ?string
|
||||||
{
|
{
|
||||||
return Arr::get($this->oldValues,$key) ? str_repeat('x',8) : NULL;
|
$pw = Arr::get($this->oldValues,$key);
|
||||||
|
return $pw
|
||||||
|
? (((($x=$this->hash($pw)) && ($x::id() !== '*clear*')) ? sprintf('{%s}',$x::shortid()) : '').str_repeat('*',16))
|
||||||
|
: NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render_item_new(int $key): ?string
|
public function render_item_new(int $key): ?string
|
||||||
{
|
{
|
||||||
return Arr::get($this->values,$key) ? str_repeat('x',8) : NULL;
|
$pw = Arr::get($this->values,$key);
|
||||||
|
return $pw
|
||||||
|
? (((($x=$this->hash($pw)) && ($x::id() !== '*clear*')) ? sprintf('{%s}',$x::shortid()) : '').str_repeat('*',16))
|
||||||
|
: NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
25
app/Classes/LDAP/Attribute/Password/Argon2i.php
Normal file
25
app/Classes/LDAP/Attribute/Password/Argon2i.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class Argon2i extends Base
|
||||||
|
{
|
||||||
|
public const key = 'ARGON2';
|
||||||
|
protected const subkey = 'i';
|
||||||
|
protected const identifier = '$argon2i';
|
||||||
|
|
||||||
|
public static function subid(string $password): bool
|
||||||
|
{
|
||||||
|
return str_starts_with(base64_decode(self::password($password)),self::identifier.'$');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return password_verify($compare,base64_decode($this->password($source)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(password_hash($password,PASSWORD_ARGON2I)));
|
||||||
|
}
|
||||||
|
}
|
25
app/Classes/LDAP/Attribute/Password/Argon2id.php
Normal file
25
app/Classes/LDAP/Attribute/Password/Argon2id.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class Argon2id extends Base
|
||||||
|
{
|
||||||
|
public const key = 'ARGON2';
|
||||||
|
protected const subkey = 'id';
|
||||||
|
protected const identifier = '$argon2id';
|
||||||
|
|
||||||
|
public static function subid(string $password): bool
|
||||||
|
{
|
||||||
|
return str_starts_with(base64_decode(self::password($password)),self::identifier.'$');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return password_verify($compare,base64_decode($this->password($source)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(password_hash($password,PASSWORD_ARGON2ID)));
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,65 @@ namespace App\Classes\LDAP\Attribute\Password;
|
|||||||
|
|
||||||
abstract class Base
|
abstract class Base
|
||||||
{
|
{
|
||||||
abstract public function compare(string $source,string $compare): bool;
|
protected const subkey = '';
|
||||||
|
|
||||||
abstract public function encode(string $password): string;
|
abstract public function encode(string $password): string;
|
||||||
|
|
||||||
public static function id(): string
|
public static function id(): string
|
||||||
|
{
|
||||||
|
return static::key.(static::subkey ? ':'.static::subkey : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the hash {TEXT}xxxx from the password
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function password(string $password): string
|
||||||
|
{
|
||||||
|
return preg_replace('/^{'.static::key.'}/','',$password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function shortid(): string
|
||||||
{
|
{
|
||||||
return static::key;
|
return static::key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When multiple passwords share the same ID, this determines which hash is responsible for the presented password
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function subid(string $password): bool
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare our password to see if it is the same as that stored
|
||||||
|
*
|
||||||
|
* @param string $source Encoded source password
|
||||||
|
* @param string $compare Password entered by user
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $this->encode($compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function salted_hash(string $password,string $algo,int $salt_size=8,string $salt=NULL): string
|
||||||
|
{
|
||||||
|
if (is_null($salt))
|
||||||
|
$salt = hex2bin(random_salt($salt_size));
|
||||||
|
|
||||||
|
return base64_encode(hash($algo,$password.$salt,true).$salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function salted_salt(string $source): string
|
||||||
|
{
|
||||||
|
$hash = base64_decode(substr($source,strlen(static::key)+2));
|
||||||
|
return substr($hash,strlen($hash)-static::salt/2);
|
||||||
|
}
|
||||||
}
|
}
|
22
app/Classes/LDAP/Attribute/Password/Bcrypt.php
Normal file
22
app/Classes/LDAP/Attribute/Password/Bcrypt.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class Bcrypt extends Base
|
||||||
|
{
|
||||||
|
public const key = 'BCRYPT';
|
||||||
|
|
||||||
|
private const options = [
|
||||||
|
'cost' => 8,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return password_verify($compare,base64_decode($this->password($source)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(password_hash($password,PASSWORD_BCRYPT,self::options)));
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,7 @@ namespace App\Classes\LDAP\Attribute\Password;
|
|||||||
|
|
||||||
final class Clear extends Base
|
final class Clear extends Base
|
||||||
{
|
{
|
||||||
public const key = 'Clear';
|
public const key = '*clear*';
|
||||||
|
|
||||||
public function compare(string $source,string $compare): bool
|
|
||||||
{
|
|
||||||
return $source === $compare;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function encode(string $password): string
|
public function encode(string $password): string
|
||||||
{
|
{
|
||||||
|
13
app/Classes/LDAP/Attribute/Password/MD5.php
Normal file
13
app/Classes/LDAP/Attribute/Password/MD5.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class MD5 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'MD5';
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(hash('md5',$password,true)));
|
||||||
|
}
|
||||||
|
}
|
13
app/Classes/LDAP/Attribute/Password/SHA.php
Normal file
13
app/Classes/LDAP/Attribute/Password/SHA.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SHA extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SHA';
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(hash('sha1',$password,true)));
|
||||||
|
}
|
||||||
|
}
|
13
app/Classes/LDAP/Attribute/Password/SHA256.php
Normal file
13
app/Classes/LDAP/Attribute/Password/SHA256.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SHA256 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SHA256';
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(hash('sha256',$password,true)));
|
||||||
|
}
|
||||||
|
}
|
13
app/Classes/LDAP/Attribute/Password/SHA384.php
Normal file
13
app/Classes/LDAP/Attribute/Password/SHA384.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SHA384 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SHA384';
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(hash('sha384',$password,true)));
|
||||||
|
}
|
||||||
|
}
|
13
app/Classes/LDAP/Attribute/Password/SHA512.php
Normal file
13
app/Classes/LDAP/Attribute/Password/SHA512.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SHA512 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SHA512';
|
||||||
|
|
||||||
|
public function encode(string $password): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,base64_encode(hash('sha512',$password,true)));
|
||||||
|
}
|
||||||
|
}
|
22
app/Classes/LDAP/Attribute/Password/SMD5.php
Normal file
22
app/Classes/LDAP/Attribute/Password/SMD5.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SMD5 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SMD5';
|
||||||
|
protected const salt = 8;
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password,string $salt=NULL): string
|
||||||
|
{
|
||||||
|
if (is_null($salt))
|
||||||
|
$salt = hex2bin(random_salt(self::salt));
|
||||||
|
|
||||||
|
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'md5',self::salt,$salt));
|
||||||
|
}
|
||||||
|
}
|
19
app/Classes/LDAP/Attribute/Password/SSHA.php
Normal file
19
app/Classes/LDAP/Attribute/Password/SSHA.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SSHA extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SSHA';
|
||||||
|
protected const salt = 8;
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password,string $salt=NULL): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha1',self::salt,$salt));
|
||||||
|
}
|
||||||
|
}
|
19
app/Classes/LDAP/Attribute/Password/SSHA256.php
Normal file
19
app/Classes/LDAP/Attribute/Password/SSHA256.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SSHA256 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SSHA256';
|
||||||
|
protected const salt = 8;
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password,string $salt=NULL): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha256',self::salt,$salt));
|
||||||
|
}
|
||||||
|
}
|
19
app/Classes/LDAP/Attribute/Password/SSHA384.php
Normal file
19
app/Classes/LDAP/Attribute/Password/SSHA384.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SSHA384 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SSHA384';
|
||||||
|
protected const salt = 8;
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password,string $salt=NULL): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha384',self::salt,$salt));
|
||||||
|
}
|
||||||
|
}
|
19
app/Classes/LDAP/Attribute/Password/SSHA512.php
Normal file
19
app/Classes/LDAP/Attribute/Password/SSHA512.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\LDAP\Attribute\Password;
|
||||||
|
|
||||||
|
final class SSHA512 extends Base
|
||||||
|
{
|
||||||
|
public const key = 'SSHA512';
|
||||||
|
protected const salt = 8;
|
||||||
|
|
||||||
|
public function compare(string $source,string $compare): bool
|
||||||
|
{
|
||||||
|
return $source === $this->encode($compare,$this->salted_salt($source));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encode(string $password,string $salt=NULL): string
|
||||||
|
{
|
||||||
|
return sprintf('{%s}%s',self::key,$this->salted_hash($password,'sha512',self::salt,$salt));
|
||||||
|
}
|
||||||
|
}
|
@ -99,11 +99,11 @@ class HomeController extends Controller
|
|||||||
|
|
||||||
$result = collect();
|
$result = collect();
|
||||||
foreach ($password as $key => $value) {
|
foreach ($password as $key => $value) {
|
||||||
$type = $password->hash_id($value);
|
$hash = $password->hash($value);
|
||||||
$compare = Arr::get($request->password,$key);
|
$compare = Arr::get($request->password,$key);
|
||||||
//Log::debug(sprintf('comparing [%s] with [%s] type [%s]',$value,$compare,$type));
|
//Log::debug(sprintf('comparing [%s] with [%s] type [%s]',$value,$compare,$hash::id()),['object'=>$hash]);
|
||||||
|
|
||||||
$result->push((($compare !== NULL) && Attribute\Password::hash($type)->compare($value,$compare)) ? 'OK' :'FAIL');
|
$result->push((($compare !== NULL) && $hash->compare($value,$compare)) ? 'OK' :'FAIL');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
@ -128,9 +128,15 @@ class HomeController extends Controller
|
|||||||
// We need to process and encrypt the password
|
// We need to process and encrypt the password
|
||||||
$passwords = [];
|
$passwords = [];
|
||||||
foreach ($request->userpassword as $key => $value) {
|
foreach ($request->userpassword as $key => $value) {
|
||||||
|
// If the password is still the MD5 of the old password, then it hasnt changed
|
||||||
|
if (($old=Arr::get($o->userpassword,$key)) && ($value === md5($old))) {
|
||||||
|
array_push($passwords,$old);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ($value) {
|
if ($value) {
|
||||||
$type = Arr::get($request->userpassword_hash,$key);
|
$type = Arr::get($request->userpassword_hash,$key);
|
||||||
array_push($passwords,Attribute\Password::hash($type)->encode($value));
|
array_push($passwords,Attribute\Password::hash_id($type)->encode($value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$o->userpassword = $passwords;
|
$o->userpassword = $passwords;
|
||||||
@ -199,8 +205,7 @@ class HomeController extends Controller
|
|||||||
|
|
||||||
return Redirect::to('/')
|
return Redirect::to('/')
|
||||||
->withInput()
|
->withInput()
|
||||||
->with('success',__('Entry updated'))
|
->with('updated',collect($dirty)->map(fn($key,$item)=>$o->getObject($item)));
|
||||||
->with('updated',$dirty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,4 +10,23 @@ function login_attr_description(): string
|
|||||||
function login_attr_name(): string
|
function login_attr_name(): string
|
||||||
{
|
{
|
||||||
return key(config('ldap.login.attr'));
|
return key(config('ldap.login.attr'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to generate a random salt for crypt-style passwords. Salt strings are used
|
||||||
|
* to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses
|
||||||
|
* not only the user's password but also a randomly generated string. The string is
|
||||||
|
* stored as the first N characters of the hash for reference of hashing algorithms later.
|
||||||
|
*
|
||||||
|
* @param int $length The length of the salt string to generate.
|
||||||
|
* @return string The generated salt string.
|
||||||
|
* @throws \Random\RandomException
|
||||||
|
*/
|
||||||
|
function random_salt(int $length): string
|
||||||
|
{
|
||||||
|
$str = bin2hex(random_bytes(ceil($length/2)));
|
||||||
|
if ($length%2 === 1)
|
||||||
|
return substr($str,0,-1);
|
||||||
|
|
||||||
|
return $str;
|
||||||
}
|
}
|
@ -670,7 +670,7 @@ function get_request($attr,$type='POST',$die=false,$default=null,$preventXSS=tru
|
|||||||
$value = isset($_POST[$attr]) ? (is_array($_POST[$attr]) ? $_POST[$attr] : (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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($die && is_null($value))
|
if ($die && is_null($value))
|
||||||
system_message(array(
|
system_message(array(
|
||||||
'title'=>_('Generic Error'),
|
'title'=>_('Generic Error'),
|
||||||
@ -1757,32 +1757,6 @@ function expand_dn_with_base($base,$sub_dn) {
|
|||||||
return sprintf('%s%s',$sub_dn,$base);
|
return sprintf('%s%s',$sub_dn,$base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to generate a random salt for crypt-style passwords. Salt strings are used
|
|
||||||
* to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses
|
|
||||||
* not only the user's password but also a randomly generated string. The string is
|
|
||||||
* stored as the first N characters of the hash for reference of hashing algorithms later.
|
|
||||||
*
|
|
||||||
* @param int The length of the salt string to generate.
|
|
||||||
* @return string The generated salt string.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split an RDN into its attributes
|
* Split an RDN into its attributes
|
||||||
*/
|
*/
|
||||||
@ -1999,368 +1973,6 @@ function draw_jpeg_photo($server,$dn,$attr_name='jpegphoto',$index,$draw_delete_
|
|||||||
$attr_name,_('Delete photo'));
|
$attr_name,_('Delete photo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the list of available password types
|
|
||||||
*
|
|
||||||
* @todo Dynamically work this list out so we only present hashes that we can encrypt
|
|
||||||
*/
|
|
||||||
function password_types() {
|
|
||||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
|
||||||
debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
|
|
||||||
|
|
||||||
return array(
|
|
||||||
''=>'clear',
|
|
||||||
'bcrypt'=>'bcrypt',
|
|
||||||
'blowfish'=>'blowfish',
|
|
||||||
'crypt'=>'crypt',
|
|
||||||
'ext_des'=>'ext_des',
|
|
||||||
'md5'=>'md5',
|
|
||||||
'k5key'=>'k5key',
|
|
||||||
'md5crypt'=>'md5crypt',
|
|
||||||
'sha'=>'sha',
|
|
||||||
'smd5'=>'smd5',
|
|
||||||
'ssha'=>'ssha',
|
|
||||||
'sha512'=>'sha512',
|
|
||||||
'sha256crypt'=>'sha256crypt',
|
|
||||||
'sha512crypt'=>'sha512crypt',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashes a password and returns the hash based on the specified enc_type.
|
|
||||||
*
|
|
||||||
* @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, sha512,
|
|
||||||
* sha256crypt, sha512crypt, or clear.
|
|
||||||
* @return string The hashed password.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
$enc_type = strtolower($enc_type);
|
|
||||||
|
|
||||||
switch($enc_type) {
|
|
||||||
case 'blowfish':
|
|
||||||
if (! defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0)
|
|
||||||
error(_('Your system crypt library does not support blowfish encryption.'),'error','index.php');
|
|
||||||
|
|
||||||
# Hardcoded to second blowfish version and set number of rounds
|
|
||||||
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$2a$12$'.random_salt(13)));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'crypt':
|
|
||||||
if ($_SESSION[APPCONFIG]->getValue('password', 'no_random_crypt_salt'))
|
|
||||||
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,substr($password_clear,0,2)));
|
|
||||||
else
|
|
||||||
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,random_salt(2)));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ext_des':
|
|
||||||
# Extended des crypt. see OpenBSD crypt man page.
|
|
||||||
if (! defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0)
|
|
||||||
error(_('Your system crypt library does not support extended DES encryption.'),'error','index.php');
|
|
||||||
|
|
||||||
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,'_'.random_salt(8)));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'k5key':
|
|
||||||
$new_value = sprintf('{K5KEY}%s',$password_clear);
|
|
||||||
|
|
||||||
system_message(array(
|
|
||||||
'title'=>_('Unable to Encrypt Password'),
|
|
||||||
'body'=>'phpLDAPadmin cannot encrypt K5KEY passwords',
|
|
||||||
'type'=>'warn'));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'md5':
|
|
||||||
$new_value = sprintf('{MD5}%s',base64_encode(pack('H*',md5($password_clear))));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'md5crypt':
|
|
||||||
if (! defined('CRYPT_MD5') || CRYPT_MD5 == 0)
|
|
||||||
error(_('Your system crypt library does not support md5crypt encryption.'),'error','index.php');
|
|
||||||
|
|
||||||
$new_value = sprintf('{CRYPT}%s',crypt($password_clear,'$1$'.random_salt(9)));
|
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
error(_('Your PHP install does not have the mhash() or mhash_keygen_s2k() function. Cannot do S2K hashes.'),'error','index.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'sha512':
|
|
||||||
if (function_exists('openssl_digest') && function_exists('base64_encode')) {
|
|
||||||
$new_value = sprintf('{SHA512}%s', base64_encode(openssl_digest($password_clear, 'sha512', true)));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
error(_('Your PHP install doest not have the openssl_digest() or base64_encode() function. Cannot do SHA512 hashes. '),'error','index.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
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 'clear':
|
|
||||||
default:
|
|
||||||
$new_value = $password_clear;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $new_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a clear-text password and a hash, this function determines if the clear-text password
|
|
||||||
* is the password that was used to generate the hash. This is handy to verify a user's password
|
|
||||||
* when all that is given is the hash and a "guess".
|
|
||||||
* @param String The hash.
|
|
||||||
* @param String The password in clear text to test.
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
if (in_array($attribute,array('sambalmpassword','sambantpassword'))) {
|
|
||||||
$smb = new smbHash;
|
|
||||||
|
|
||||||
switch($attribute) {
|
|
||||||
case 'sambalmpassword':
|
|
||||||
if (strcmp($smb->lmhash($plainpassword),strtoupper($cryptedpassword)) == 0)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case 'sambantpassword':
|
|
||||||
if (strcmp($smb->nthash($plainpassword),strtoupper($cryptedpassword)) == 0)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/{([^}]+)}(.*)/',$cryptedpassword,$matches)) {
|
|
||||||
$cryptedpassword = $matches[2];
|
|
||||||
$cypher = strtolower($matches[1]);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$cypher = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($cypher) {
|
|
||||||
# SSHA crypted passwords
|
|
||||||
case 'ssha':
|
|
||||||
# Check php mhash support before using it
|
|
||||||
if (function_exists('mhash')) {
|
|
||||||
$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);
|
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
# SHA crypted passwords
|
|
||||||
case 'sha':
|
|
||||||
if (strcasecmp(pla_password_hash($plainpassword,'sha'),'{SHA}'.$cryptedpassword) == 0)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
# MD5 crypted passwords
|
|
||||||
case 'md5':
|
|
||||||
if( strcasecmp(pla_password_hash($plainpassword,'md5'),'{MD5}'.$cryptedpassword) == 0)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
# Crypt passwords
|
|
||||||
case 'crypt':
|
|
||||||
# Check if it's blowfish crypt
|
|
||||||
if (preg_match('/^\\$2+/',$cryptedpassword)) {
|
|
||||||
|
|
||||||
# Make sure that web server supports blowfish crypt
|
|
||||||
if (! defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH == 0)
|
|
||||||
error(_('Your system crypt library does not support blowfish encryption.'),'error','index.php');
|
|
||||||
|
|
||||||
list($version,$rounds,$salt_hash) = explode('$',$cryptedpassword);
|
|
||||||
|
|
||||||
if (crypt($plainpassword,'$'.$version.'$'.$rounds.'$'.$salt_hash) == $cryptedpassword)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if it's an crypted md5
|
|
||||||
elseif (strstr($cryptedpassword,'$1$')) {
|
|
||||||
|
|
||||||
# Make sure that web server supports md5 crypt
|
|
||||||
if (! defined('CRYPT_MD5') || CRYPT_MD5 == 0)
|
|
||||||
error(_('Your system crypt library does not support md5crypt encryption.'),'error','index.php');
|
|
||||||
|
|
||||||
list($dummy,$type,$salt,$hash) = explode('$',$cryptedpassword);
|
|
||||||
|
|
||||||
if (crypt($plainpassword,'$1$'.$salt) == $cryptedpassword)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if it's extended des crypt
|
|
||||||
elseif (strstr($cryptedpassword,'_')) {
|
|
||||||
|
|
||||||
# Make sure that web server supports ext_des
|
|
||||||
if (! defined('CRYPT_EXT_DES') || CRYPT_EXT_DES == 0)
|
|
||||||
error(_('Your system crypt library does not support extended DES encryption.'),'error','index.php');
|
|
||||||
|
|
||||||
if (crypt($plainpassword,$cryptedpassword) == $cryptedpassword)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Password is plain crypt
|
|
||||||
else {
|
|
||||||
|
|
||||||
if (crypt($plainpassword,$cryptedpassword) == $cryptedpassword)
|
|
||||||
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;
|
|
||||||
|
|
||||||
# No crypt is given assume plaintext passwords are used
|
|
||||||
default:
|
|
||||||
if ($plainpassword == $cryptedpassword)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects password encryption type
|
* Detects password encryption type
|
||||||
*
|
*
|
||||||
|
2
public/css/custom.css
vendored
2
public/css/custom.css
vendored
@ -9,7 +9,7 @@ div#userpassword .select2-container--bootstrap-5 .select2-selection {
|
|||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
border-bottom-right-radius: unset;
|
border-bottom-right-radius: unset;
|
||||||
border-top-right-radius: unset;
|
border-top-right-radius: unset;
|
||||||
width: 7em;
|
width: 9em;
|
||||||
border: #444054 1px solid;
|
border: #444054 1px solid;
|
||||||
background-color: #f0f0f0;
|
background-color: #f0f0f0;
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
@foreach($o->values as $value)
|
@foreach($o->values as $value)
|
||||||
@if($edit)
|
@if($edit)
|
||||||
<div class="input-group has-validation mb-3">
|
<div class="input-group has-validation mb-3">
|
||||||
<x-form.select class="password" id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[]" :value="$o->hash_id($value)" :options="$helpers" allowclear="false" disabled="true"/>
|
<x-form.select id="userpassword_hash_{{$loop->index}}" name="userpassword_hash[]" :value="$o->hash($value)->id()" :options="$helpers" allowclear="false" disabled="true"/>
|
||||||
<input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>$o->values->contains($value)]) name="{{ $o->name_lc }}[]" value="{{ md5($value) }}" @readonly(true)>
|
<input type="password" @class(['form-control','is-invalid'=>($e=$errors->get($o->name_lc.'.'.$loop->index)),'mb-1','border-focus'=>$o->values->contains($value)]) name="{{ $o->name_lc }}[]" value="{{ md5($value) }}" @readonly(true)>
|
||||||
|
|
||||||
<div class="invalid-feedback pb-2">
|
<div class="invalid-feedback pb-2">
|
||||||
@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
{{ (($x=$o->hash_id($value)) && ($x !== 'Clear')) ? sprintf('{%s}',$x) : '' }}{{ str_repeat('x',8) }}
|
{{ (($x=$o->hash($value)) && ($x::id() !== '*clear*')) ? sprintf('{%s}',$x::shortid()) : '' }}{{ str_repeat('*',16) }}
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</x-attribute.layout>
|
</x-attribute.layout>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<x-form.base {{ $attributes }}>
|
<x-form.base {{ $attributes }}>
|
||||||
@isset($name)
|
@isset($name)
|
||||||
<input type="hidden" id="{{ $name }}_disabled" name="{{ $name }}" value="" disabled>
|
<input type="hidden" id="{{ $id ?? $name }}_disabled" name="{{ $name }}" value="" disabled>
|
||||||
@endisset
|
@endisset
|
||||||
<select style="width: 80%" class="form-select @isset($name)@error((! empty($old)) ? $old : $name) is-invalid @enderror @endisset" id="{{ $id ?? $name }}" @isset($name)name="{{ $name }}"@endisset @required(isset($required) && $required) @disabled(isset($disabled) && $disabled)>
|
<select style="width: 80%" class="form-select @isset($name)@error((! empty($old)) ? $old : $name) is-invalid @enderror @endisset" id="{{ $id ?? $name }}" @isset($name)name="{{ $name }}"@endisset @required(isset($required) && $required) @disabled(isset($disabled) && $disabled)>
|
||||||
@if(empty($value) || isset($addnew) || isset($choose))
|
@if(empty($value) || isset($addnew) || isset($choose))
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-up"></i> Success!</h4>
|
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-up"></i> Success!</h4>
|
||||||
<hr>
|
<hr>
|
||||||
<p>{{ session()->pull('success') }}</p>
|
|
||||||
<ul style="list-style-type: square;">
|
<ul style="list-style-type: square;">
|
||||||
@foreach (session()->pull('updated') as $key => $values)
|
@foreach (session()->get('success') as $item)
|
||||||
<li>{{ $key }}: {{ join(',',$values) }}</li>
|
<li>{{ $item }}</li>
|
||||||
@endforeach
|
@endforeach
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
12
resources/views/components/updated.blade.php
Normal file
12
resources/views/components/updated.blade.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
@if(session()->has('updated'))
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<h4 class="alert-heading"><i class="fas fa-fw fa-thumbs-up"></i> Success!</h4>
|
||||||
|
<hr>
|
||||||
|
<p>{{ __('Entry updated') }}</p>
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
@foreach (session()->pull('updated') as $key => $o)
|
||||||
|
<li><abbr title="{{ $o->description }}">{{ $o->name }}</abbr>: {{ $o->values->map(fn($item,$key)=>$o->render_item_new($key))->join(',') }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
@section('main-content')
|
@section('main-content')
|
||||||
<x-note/>
|
<x-note/>
|
||||||
<x-success/>
|
<x-updated/>
|
||||||
<x-error/>
|
<x-error/>
|
||||||
|
|
||||||
<!-- @todo If we are redirected here, check old() and add back any attributes that were in the original submission -->
|
<!-- @todo If we are redirected here, check old() and add back any attributes that were in the original submission -->
|
||||||
@ -136,7 +136,7 @@
|
|||||||
@if($up=$o->getObject('userpassword'))
|
@if($up=$o->getObject('userpassword'))
|
||||||
<!-- CHECK USERPASSWORD -->
|
<!-- CHECK USERPASSWORD -->
|
||||||
<div class="modal fade" id="userpassword-check-modal" tabindex="-1" aria-labelledby="userpassword-check-label" aria-hidden="true">
|
<div class="modal fade" id="userpassword-check-modal" tabindex="-1" aria-labelledby="userpassword-check-label" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-md modal-fullscreen-md-down">
|
<div class="modal-dialog modal-lg modal-fullscreen-lg-down">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5" id="userpassword-check-label">Check Passwords for {{ $dn }}</h1>
|
<h1 class="modal-title fs-5" id="userpassword-check-label">Check Passwords for {{ $dn }}</h1>
|
||||||
@ -148,7 +148,7 @@
|
|||||||
@foreach($up->values as $key => $value)
|
@foreach($up->values as $key => $value)
|
||||||
<tr>
|
<tr>
|
||||||
<th>Check</th>
|
<th>Check</th>
|
||||||
<td>{{ (($xx=$up->hash_id($value)) && ($xx !== 'Clear')) ? sprintf('{%s}',$xx) : '' }}{{ str_repeat('x',8) }}</td>
|
<td>{{ $up->render_item_old($key) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="password" style="width: 90%" name="password[{{$key}}]"> <i class="fas fa-fw fa-lock"></i>
|
<input type="password" style="width: 90%" name="password[{{$key}}]"> <i class="fas fa-fw fa-lock"></i>
|
||||||
<div class="invalid-feedback pb-2">
|
<div class="invalid-feedback pb-2">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user